Create custom Twig node and parser #DSL

If You want to create custom twig node then this tutorial is for You. I will show you step by step how to create custom twig syntax (DSL) called gimme (we build it for our Superdesk Publisher project).

Read more about this publisher feature here: Building a Template System for Your PHP Application.

Lest start with simplecomposer.json file:

{
"require": {
"twig/twig": "^2.4"
},
"autoload": {
"psr-4": {
"SWP\\": "src/SWP/"
}
}
}

and run php composer.phar install command.

let’s create demo entry point index.php

<?php
// load composer autoloader
require_once
__DIR__.'/vendor/autoload.php';
// define Twig loader with our simple template
$loader = new Twig_Loader_Array([
'index' => '{% gimme article with {\'foo\': \'bar\'} %} {{ dump(article) }} {% endgimme %}',
]);
// create Twig instance and pass there our loader (and enable debug extension).
$twig = new Twig_Environment($loader, ['debug' => true]);
$twig->addExtension(new \Twig_Extension_Debug());
// register our custom extension
$twig->addExtension(new \SWP\Extension\GimmeExtension());

echo $twig->render('index');

First we need to create Twig Extension:

src/SWP/Extension/GimmeExtension.php

Extension allows to register custom things in twig. Read more about it in docs: https://twig.symfony.com/doc/2.x/advanced.html#creating-an-extension. Our extension is simple and register only TokenParser and simplified data loader (in real world you will inject here some repository or provider).

First let’s look at our custom node syntax:

{% gimme article with {'foo': 'bar'} %} {# loaded data will be visible under `article` variable. #} {{ dump(user) }} {% endgimme %}

Step by step:

  • gimme — tell for twig that you want to start our node
  • article — this can tell for your loader what kind of data you want to load (data will be also available under this variable inside block).
  • with — (optional) this will tell for parser that we pass extra parameters for loader
  • {'foo': 'bar'} — (optional) extra parameters passed to loader
  • endgimme — tell for twig that you want to close our node

Now we need to write that GimmeTokenParser (responsible for parsing the template code) [Docs can be found here].

src/SWP/Parser/GimmeTokenParser.php

TokenParser creates Node instance. Node is responsible for converting the parsed code to PHP.

src/SWP/Node/GimmeNode.php

Full working example can be found in this repository: https://github.com/ahilles107/twig-node-parser-tutorial

Check out our final implementation (with gimmelist — node for collections loading with support for pagination) here: https://github.com/SuperdeskWebPublisher/templates-system

Thanks for reading this post. You can follow me on twitter: https://twitter.com/ahilles107 and on linkedin: https://www.linkedin.com/in/pawelmikolajczuk/