We’re looking at allowing a way to embed custom code into a PHP application, and exploring secure/sandboxed ways to do that (e.g. if you’ve used Apex
in Salesforce, or are familiar with ExpressionLanguage
in Symfony
, that kind of thing).
One thing we’ve exploring is allowing custom Twig
to run, but the one downside to Twig is that it’s really designed as a template language, so it’s logic like this is sort of clunky because of all the extra brackets:
{% if foo.bar == 'test' %}
{% for line in lines %}
{% if line.rate > 10 %}
... more code here ...
{% endif %}
{% endfor %}
{% endif %}
It would be much cleaner/easier if we could just write:
if foo.bar == 'test'
{
for line in lines {
if line.rate > 10
{
... more code here ...
}
}
}
Is it possible / has anyone seen Twig extended to support multiple lines of code, and not require all of the {%
and %}
?
Or failing that… has anyone seen any other option for safely embedding logic in a PHP app? We’ve also looked at the PHP Lua
extension as a potential option, but I’m not sure how maintained it is…
2
It’s hard to say without seeing your specific templates, but arguably, Twig templates shouldn’t have logic in them — that’s kind of the point of an MVC design. If your templates are this complicated, then you should probably look at moving some of that code into the controller, rather than looking for a view layer tool that supports doing things that shouldn’t be done in the view layer.
I think the solution in your case is simply to use smaller templates. For example, if the template is internally toggling between two different states:
{% if foo.bar == 'test' %}
... some large chunk
{% else %}
... some other large chunk
{% endif %}
Make two different templates, and conditionally render one of them:
$this->render($foo->bar === 'test' ? 'test.twig.html' : 'not_test.twig.html');
Or even:
$this->render($foo->bar . '.twig.html');
Also note, most if
statements can be shortened to a ternary, and Twig supports shorthand ternaries, which makes this:
{% if line.rate > 10 %}
{{ line.rate }}
{% endif %}
Into just this:
{{ line.rate > 10 ? line.rate }}
And if you have a large template chunk for each iteration of a loop, you can always pull the row template into its own partial:
{% for line in lines %}
{% include 'row_template.html.twig' %}
{% endfor %}