Using Twig in Yii2

 Apr 10, 2015

I was recently working on a project where the initial mockups were all built using Twig and a light weight Silex backend, but the actual application was built in Yii2. Rather than rebuild all the UI as Yii2 views, I looked into utilising the Twig elements I already had. It was a lot easier than I hoped to integrate Twig into Yii2 and I didn’t loose out on any of Yii2’s powerful view features.

Initially the mockups were built out as a semi-static site using Silex and Twig templates to make it quick to put together a high resolution mock-up and have some fake data passed around to give a feel for the app.

However, the actual app that was being built in-house by my client utilised the Yii2 framework. So, rather than re-do all the work from the mockups, we looked at how we could re-use the Twig templates as the view layer for the Yii2 project.

Requisites

First off you need to add the Yii2 Twig renderer to your composer.json. Go to the root directory (where the composer.json resides) and type

composer require yiisoft/yii2-twig

This assumes you have composer installed globally in your /bin directory

Then you need to tell Yii to use this new renderer.

In the config/web.php file of your Yii project you need to add the following section to your components hash

'components' => [
    'view' => [
        'renderers' => [
            'twig' => [
                'class' => 'yii\twig\ViewRenderer',
                // set cachePath to false in order to disable template caching
                'cachePath' => false, //'@runtime/Twig/cache',
                // Array of twig options:
                'options' => [
                    'auto_reload' => true,
                ],
                // add Yii helpers or widgets here
                'globals' => [
                    'html' => '\yii\helpers\Html',
                ]
            ]
        ]
    ]
],
// -- snip

Lastly, and optionally, we wanted to use Twig throughout the application, so we globally replaced the layout for the whole app in the config with a Twig variant.

In the same file, at the route of the $config array, add a new layout key

$config = [
  'layout' => 'main.twig',
  // -- snip -- //
];

This tells Yii to ignore the default views/layouts/main.php and use the views/layouts/main.twig instead

Now all the set up is done and Yii knows how to render Twig templates. Now I’ll go through basic usage.

Setting up a Twig Layout

Now we’ve made those changes we need a Twig layout to replace the main.php.

Create the new file in views/layouts/main.twig

Here is the absolute minimum you need to get started:

{{ this.beginPage() }}
<!doctype html>
<html lang="{{app.language}}">
    <head>
      <meta charset="{{app.charset}}"/>
      <meta name="viewport" content="width=device-width, initial-scale=1">      
      {{ html.csrfMetaTags() | raw }}
        <title>{{ html.encode(this.title) }}</title>
      {{ this.head() }}
    </head>
  <body>
    {{ this.beginBody() }}
      {{ content | raw }}
    {{ this.endBody() }}
  </body>
</html>
{{ this.endPage() }}

This is a basic replacement for the default main.php that comes with Yii2 but in Twig with the Bootstrapped navigation and footer removed. On good thing to note here is that as we are merging in the content variable, it means that we can use either Twig views, or the normal Yii PHP views. Both will render as HTML that will then be merged in.

Using a Twig Template

Assuming we have a PostsController to display posts on our Blog application, the actionIndex may look something like this

public function actionIndex()
{
  $posts = Posts::find()->where(['published' => Posts::PUBLISHED])->orderBy('published_at');

  return $this->render('index.twig', [
    'posts' => $posts
  ]);
}

The important thing to notice here is that you must put the .twig extension in the $this->render call, otherwise Yii will attempt to load the normal index.php view file.

With this in place you can now create your first Twig view file. Start by creating views/posts/index.twig.

Now you can build the view using all the tools available to you in Twig, and pull in anything you need from Yii.

For (a very basic) example:

{% for post in posts %}
<div class="post">
  <h1>{{ post.title }}</h1>
  <div class="post-body">
    {{ post.body }}
  </div>
</div>
{% endfor %}

Resources

You can read up more on Twig itself at the official documentation http://twig.sensiolabs.org/documentation and about the Yii2 Twig Renderer along with some Yii specific syntax at the Github repo