We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Inherit dynamic template in Phalcon Volt

I need to load a page, that will be "inserted" in a template - as I read it, Volt's Template Inheritance should do the trick and it does... kinda. Hardcoded values, as shown in the examples, work fine - the following example works:

<!-- Template --> <div id="site_content">
{% block test %} {% endblock %} </div>

and the page, that inherits the template:

{% extends "../../templates/de/index.volt" %}

{% block test %} {{ content() }} {# this is a registered volt function that outputs the generated content #} {% endblock %}

However, the same page might need to inherit a different template and that must be decided on runtime, so the name of the template must be generated dynamically. Two options occurred to me:

  • Set the template name to a variable and use it when extending - the problem here is that I don't see a way to use it afterwards. That guy seems to have had the same problem, but there is neither an answer of how to do it, nor a confirmation that it isn't possible at all.
  • Register another function to generate the complete string (e.g. {% extends "../../templates/de/index.volt" %}) and then compile it, e.g.

$compiler->addFunction('get_template', function ($resolvedArgs, $exprArgs) use ($volt) { return $volt->getCompiler() ->compileString('{% extends "../../templates/de/index.volt" %}'); });

and then use that function in the page, e.g.

{{ get_template() }}

{% block test %} {{ content() }} {% endblock %}

However, using that approach does not parse the page content (e.g. the content returned by the registered content() function is not shown). I'm also open to other solutions (using Twig instead of Volt is only a last resort, for performance issues), advices of what I'm doing wrong or pointers of useful articles on the topic. Thanks in advance!



92

Unfortunately, I don't have the answer, but hopefully my findings from a little playing may help you eventually get there, or may help somone else trying the same in the future.

My initial idea was to have a static extend statement, such as {% extends "../../templates/get_template.volt" %}.

Then to set the template you want to load using php:

    $this->view->template = "../../templates/de/index.volt";

And within get_template.volt to load the template specified by php:

{% include template %}

All of the above works, however the blocks within index.volt will not be parsed, but stripped out. The only way I can see to get around that is to then use the include method, rather than blocks - but this defeats the purpose of using extend all together.

Best of luck finding a solution.