/silverstripe-twig

Allows the use of twig as a template engine in SilverStripe

Primary LanguagePHP

Twig templates for SilverStripe 4

Overview

SilverStripe Twig enables the use of the Twig templating engine in SilverStripe 4

If you are not familiar with Twig, check out the docs.

Installation

Composer

Create or edit a composer.json file in the root of your SilverStripe project, and make sure the following is present.

{
    "require": {
        "camspiers/silverstripe-twig": "0.0.*",
		"camspiers/autoloader-composer-silverstripe": "1.0.*"
    }
}

After completing this step, navigate in Terminal or similar to the SilverStripe root directory and run composer install or composer update depending on whether or not you have composer already in use.

Getting started

What to name and where to put your templates

Create a folder called twig in your current theme. This is where twig will look for your templates. By default Twig expects your templates to be named with the .twig extension, but can be easily configured to look for others (see twig.extensions).

The way SilverStripe twig decides which template to use is the same way SilverStripe selects .ss templates.

It builds a ranked list of candidate templates based on the class name of the current controller or dataRecord and the action being called. Using the template list it selects the first template that it finds.

For example, for page of PageType Page. If there is a Page.twig template in the twig folder it will use that.

How to enable twig

Twig rendering is enabled by extending the functionality of your SilverStripe controller. This can be done in two ways depending on what version of PHP you have.

PHP 5.4

The PHP 5.3 classes above are actually auto-generated from a trait. To use the trait add a use statement in your controller as follows:

class Page_Controller extends ContentController
{
	use TwigControllerTrait;
}

or:

class MyController extends Controller
{
	use TwigControllerTrait;
}

Accessing your Controller in twig

By default twig makes your controller (and therefore your dataRecord) available in your template by the variable c.

{% for Page in c.Pages %}
	{{ Page.Title }}
{% endfor %}
<title>{{ c.Title }}</title>
<ul>
{% for Page in c.Menu(1) %}
	<li>{{ Page.Title }}</li>
{% else %}
	<li>No pages</li>
{% endfor %}
</ul>

Rendering HTML Generating Controller Methods

  • SS4 changes the __toString behaviour for ViewableData objects to use static::class rather than $this->forTemplate()
  • We need to dump the raw HTML value or we get escaped output
{{ c.Form.forTemplate|raw }}

Practical usage example

Achieving similar functionality to SilverStripe's $Layout variable is easy with twig.

Twig has the concepts of extends and blocks which enable flexible template reuse.

Page.twig

{% extends "layouts/layout.twig" %}

{% block head %}
	{{ parent() }}
	{# add some extra assets here #}
{% endblock %}

{% block header %}
	{# add some header content here #}
{% endblock %}

{% block content %}
	<h1>{{ c.Title }}</h1>
{% endblock %}

layouts/layout.twig

<html>
	<head>
		{% block head %}
			{# default assets here #}
		{% endblock %}
	</head>
	<body>
		{% block header %}{% endblock %}
		{% block content %}{% endblock %}
	</body>
</html>

Configuration

SilverStripe Twig uses a dependency injection container (an extension of Pimple) to allow configuration and DI for all objects used.

Options

  • twig.environment_options
  • twig.extensions
  • twig.compilation_cache
  • twig.template_paths
  • twig.controller_variable_name

An example:

mysite/_config.php

TwigContainer::extendConfig(array(
	'twig.environment_options' => array(
        'debug' => true
    ),
    'twig.extensions' => array(
    	'.twig',
    	'.html'
    ),
    'twig.compilation_cache' => BASE_PATH . '/silverstripe-cache',
    'twig.template_paths' => array(
    	THEMES_PATH . '/my-theme/templates'
    ),
    'twig.controller_variable_name' => 'controller'
));

Namespaced paths

Support for twig namesapces can be enabled by adding a twig.template_namespaced_paths array to the config. For example.

TwigContainer::extendConfig([
    "twig.template_namespaced_paths" => [
        BASE_PATH . '/node_modules/path/to/namespaced/twig/files' => 'namespace',
		BASE_PATH . '/node_modules/path/to/namespaced/twig/files' => 'anotherNamespace',
    ],
]);

This will allow the use of twig files that depend on namespaced paths, for example ExampleThirdPartyModule.twig

{% extends "@namespace/component.twig" %}
{% from "@anotherNamespace/form/form.twig" import form %}
{% from "@anotherNamespace/field/field.twig" import field %}
{% from "@anotherNamespace/input/input.twig" import input %}

More info about twig namespaces can be found at https://symfony.com/doc/current/templating/namespaced_paths.html

Any service provided by SilverStripe Twig can be accessed by instantiating the Container.

$dic = new TwigContainer;
$dic['twig']->loadTemplate('template.twig')->render();

See Pimple for more information.

Using Twig and Haml together

SilverStripe twig supports the use of haml through the SilverStripe haml module.

Install the SilverStripe haml module and you are ready to go.

You can now name your files .haml (though you don't have to).

Usage

To get Twig to process your file as Haml add:

{% haml %}

To the top of any template you want to be processed as haml.

Example:

{% haml %}
!!!
%html
	%head
		%title #{ c.Title } | haml and twig
		- block head
			:javascript
				console.log('yay');
	%body
		- block content
			%h1 #{ c.Title }
			%p #{ c.Content|raw }
			%span.created #{ c.Created|date("d/m/Y") }

Contributing

Code guidelines

This project follows the standards defined in:


License

SilverStripe Twig is released under the MIT license