So I started working a plugin which enables working with Twig templates. It requires Kirby’s 2.3.0 beta.
Code and documentation here:
Compatibility
Kirby’s chaining API for pages etc. is quite compatible with Twig
Page Models and Controllers should be fully compatible (haven’t checked yet but no reason why it wouldn’t work)
Helper functions can be exposed to the templates (e.g. {{ snippet('nav') }}) but we need to list them explicitly, which I’m a bit reluctant to do but hey. (Update: so I did that, making a list of helper functions for Kirby/Kirby Toolkit which seem relevant to templating. Not fully documented yet.)
I’m subclassing the Kirby\Component\Template component, so if there are bugfixes in Kirby’s code for this component the bug fixes won’t be picked up. And if its (small) API changes, the plugin will break your site.
Performance
I’ve just used the <?php echo memory(); ?> / {{ memory() }} helper to print memory usage in equivalent PHP and Twig templates (both querying and listing all pages in a small site, with a bit more than 100 pages).
Empty template: PHP 2.86 MB, Twig 4.74 MB
Listing all pages: PHP 5.4 MB, Twig 7.8 MB
So there’s an overhead, but it seems to be rather linear (+ 2MB) and not proportional (or not by much).
Of course that’s probably a very limited and imperfect test.
With Kirby’s default PHP templating, you can access all of PHP and also any function defined in a plugin or in a PHP file you import.
With Twig, you’re limited to what Twig provides and to variables, objects and functions provided to the Twig environment. In the plugin I’m providing the page, pages, site and kirby objects, as well as some of Kirby’s helpers and functions. This leaves two open questions:
Which functions from Kirby’s helpers or the Kirby Toolkit should be available in Twig templates? Right now I’m explicitly listing Kirby helpers to expose to Twig: https://github.com/fvsch/kirby-twig/blob/master/twig.php#L36. I’m also not exposing the Toolkit’s classes at all.
Functions from plugins are not exposed at all. I’m wondering if I should expose them, and how. I don’t think I can automatically expose them all (I don’t know how I would get a list, and there might be conflicts with built-in Twig functions). I could provide a way for other plugins to register their functions, though.
new feature: in debug mode, Twig errors will now render a nice error page with a readable message and the relevant lines from the failing Twig template
many small bug fixes (and probably introduced some bugs ^^)
now using a namespace: Kirby\Plugin\Twig (new developer guide doc recommends using a namespace but doesn’t recommend a naming convention)
undefined variables will raise an error in debug mode but not in production
added config() as an alias to c::get() (since you can’t use static methods of a class in Twig, and getting — not setting — config values seemed useful)
Version number: for some reason I had versioned it as 1.1 then bumped to 1.2 because I forgot that previous change. That’s what I get for not having a changelog. Also adding a namespace is a breaking change but I don’t suspect people were using the class directly so I didn’t bump to 2.0 just for that.
Limitations are not so bad
Unlike PHP templates, Twig doesn’t have access to all the functions and classes in the PHP script’s scope. This means that if you write a plugin file to expose a simple function to your templates… sorry, doesn’t work. Want to use the Kirby Toolkit in your Twig templates? Sorry, doesn’t work either.
I converted my personal site to Twig templates. It had legacy Kirby 1.x and 2.0 stuff all over the place, so I wasn’t sure it was going to work. Turns out it wasn’t a problem.
I replaced my custom filtering function with a Page method.
Most of my templates had 10-20 lines of PHP at the start to fetch or prepare content. I moved that to controllers.
I wrote one or two Page methods, and a Site method as well to replace another utility function.
All in all, Twig’s limitations forced me to make better use of Kirby’s tools for separating concerns and moving logic out of the templates.
I’m still considering a way to tell the Twig plugin to expose some custom functions, and considering whether I should expose bits of the toolkit or even all of it to Twig templates.
For the toolkit I could expose a function that allow instantiating any toolkit class, like {{ toolkit('c').get('something', 'fallback value') }}, but frankly I’m not sure that’s useful. Like 90% of the toolkit is better suited for use in Page methods, controllers, plugins etc.
So maybe just a way to register a custom function or class and expose it to templates.
Answer to the first question is here in the doc. Your config is okay, but the syntax when using the declared function should be {{ str__email(...) }}.
For the record, I think that if you’re sending an email on a page request you should probably manage that in a controller (site/controllers/templatename.php) and not in the template (site/templates/templatename.php or site/templates/templatename.twig). Even if not using Twig templates, it’s probably better to separate concerns this way.
It is possible to use twig for a snippets or this is only limited to the templates?
The snippet() function is Kirby’s function so snippet('test') will load site/snippets/test.php. Snippets can’t use Twig syntax. But Twig includes basically work in the same way:
{% include 'blocks/test.twig' with {var1:'lol', var2:'what'} %}
will load site/templates/blocks/test.twig.
Personally I stopped using snippets and just use the site/templates folder and some subfolders if I have many parts and want to be organized. Also template extending is great, so if you’re doing things like this:
{% include 'blocks/header.twig' %}
Page content
{% include 'blocks/footer.twig' %}
… that’s not the Twig way and it can be improved quite a bit.
As a side note, in 3.0+ and some earlier versions of this plugin, you can use the @snippets namespace to include Twig templates from the site/snippets folder:
{% include '@snippets/mysnippet.twig' %}
You can also define your own namespaces (which point to a folder) in your configuration (Kirby Twig 3.0+):
Hi,
is it possible to get the (PanelBar Plugin) working with the twig engine?
The usual way is to include the call in in your php-template:
<?php snippet('plugin.panelBar) ?>
I tried by adding the following to my config
c::set([‘twig.function.panelBar’ => panelBar]);
and calling with it in the template by
{{ panelBar }}
This doesn’t work. Not sure it its possible anyway to include plugins or more complex code in that way. I am not very skilled in respect of the php/backend stuff.
[quote=“wolle, post:14, topic:3823”]
The usual way is to include the call in in your php-template:
<?php snippet('plugin.panelBar) ?>[/quote]
You can use the snippet function as well in your Twig templates:
{{ snippet('plugin.panelBar') }}
If panelBar is a PHP function, you can indeed make it available in Twig templates, but you will need to use the function’s name as a string:
c::set('twig.function.panelBar', 'panelBar');
Then you can call the function in your templates:
{{ panelBar() }}
But I’m not seeing a panelBar function in the plugin’s documentation, so I don’t think this would work. The correct way to include the panelBar HTML, CSS and JS code seems to be using the snippet function.