2

I'm working on a plugin where I set a variable from my template. The plugin also provides a Twig filter that makes use of that variable.

{% do craft.myPlugin.setVar('example') %}

{# Filter appends 'example' to the entry title #}
{{ entry.title|myFilter }}

One thing I'd like to do is to make it possible to set the variable anywhere in my template, but still provide it to the Twig filter everywhere it is used (within that template).

{{ entry.title|myFilter }}
{% do craft.myPlugin.setVar('example') %}
{{ entry.body|myFilter }}

Yes, this probably is a very very stupid question and this cannot be done. But maybe there's a chance I'm overlooking something and you can influence the parse order or do some magic to make this possible? Any answers welcome :)

3

Short answer: Cannot be done :)

Twig doesn't really have a "parse order", it compiles to plain old PHP. Upon compilation, this would make your Twig snippet basically this:

$myVariable = 'someInitialValue';
echo $entry->title . $myVariable;
$myVariable = 'example';
echo $entry->title . $myVariable;

Obviously, setting $myVariable to "example" the second time won't affect the output of the first echo statement.

An obvious way of accomplishing basically the same thing, would be to wrap the whole template in a {% set %} call – then your options would be many, you could for instance use placeholders and the replace filter:

{% set myContent %}
   {{ entry.title | myFilter }} {# myFilter appends placeholder "%myPlaceholder%" to the input #}
{% endset %}
{# Echo the template, replacing the placeholders with whatever #}
{{ myContent | replace( { "%myPlaceholder%", craft.myPlugin.getVar } ) }}

I get that this is not what you really want though.

If you really want to get your hands dirty you can see if you can find a way to manipulate the Twig internals.

You can access the Twig instance in your plugin via the TemplatesService:

$twig = craft()->templates->twig;

I guess that one way to achieve what you want is to write your own Lexer – fairly ambitious stuff for doing something easily done by extends, embeds or by output buffering/set and replace as per my example above.

Other concepts to look at (which may or may not be useful to your quest!) are Template hooks, global Twig variables, template embedding or Twig's StringLoader extension.

Finally, I'm quite curious about the actual use case here. If you'd care to elaborate, I'd love to know why you need/want to do this.

| improve this answer | |
  • If only I'd be capable of writing such stuff as a custom Lexer, Mats! Unfortunately I'm not even close, and as all other options you listed wont do it, I probably have to get away from the idea of making it possible. It's not absolutely necessary to get my plugin working, so it's not that big of an issue. Thanks for your answer, I actually really like that creative suggestion of using a set block and I'll update the question with some more insight into what exactly I'm doing. – carlcs Mar 8 '15 at 8:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.