Integrating Twig in your legacy code, Part 2: a less wild approach

In my last post I wrote about integrating Twig into your legacy code with a really wild approach.

Today I came up with a better solution that lets you take advantage of Twig full features without any hack (like the partial tag I was talking about in my previous post).

Instead of parsing the generated output as a string with Twig, we can store it into a template, which lets us use features like use, extends, include, thing that is almost impossible – in a clean way – if we use the Twig string loader:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

class Framework_Base_Controller
{
  public function render($templateName, array $parameters = array())
  {
      // ....
      // do stuff to render your template
      // we have the HTML output in the $templateOutput variable
      // ...

        $twig = new Twig_Environment(new Twig_Loader_String(), array(
          'autoescape' => false,
      ));

        return $twig->render($templateOutput, $parameters);
  }
}

Instead of using the Twig_String_Loader we would use an array loader, and store $templateOutput in a unique template, called __MAIN__.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

class Framework_Base_Controller
{
  public function render($templateName, array $parameters = array())
  {
      // ....
      // do stuff to render your template
      // we have the HTML output in the $templateOutput variable
      // ...

      $finder     = new Symfony\Component\Finder\Finder();
      $templates  = array();

      foreach ($finder->in('/path/to/twig/templates') as $file) {
          if (!$file->isDir()) {
              $templates[$file->getRelativePathName()] = $file->getContents();
          }
      }

      $loader = new Twig_Loader_Array($templates);
        $loader->setTemplate('__MAIN__', $templateOutput);

      $twig = new Twig_Environment($loader, array(
          'autoescape' => false,
      ));

      try {
          return $this->twig->render($templateName, array(...));
      } catch (Twig_Error_Loader $e) {
          return $this->twig->render("__MAIN__", array(...));
      }
  }
}

And that’s it!

Now you can write your own $templateName:

/path/to/twig/templates/$templateName
1
2
3
4
5
6
7
{ % extends '__MAIN__' % }

{ % use 'whatever' % }

{ % block somewhat % }
  some content
{ % endblock % }

In the mood for some more reading?

...or check the archives.