Can Twig_SimpleFunction change the context?

Is it possible to change the current context of a branch by calling the Twig_Simple function?

I have registered the following function:

<?php namespace Craft; class TwiggedTwigExtension extends \Twig_Extension { public function getName() { return 'Twigged'; } public function getFunctions() { return array( 'setContextVar' => new \Twig_SimpleFunction('setContextVar', array($this, 'setContextVar'), array('needs_context' => true)), ); } public function setContextVar($context, $str, $val) { $context['context'][$str] = $val; var_dump(array_keys($context['context'])); } } 

When called from a template like {{ setContextVar('hellow', 'world') }} , var_dump shows the changed context. But a quick check in the template, like {{ dump(_context|keys) }} , does not display the changed context.

Am I going about it wrong?

+5
source share
2 answers

This is not possible with functions because context is not passed by reference.

In your extension, you even get access to $context['context'] , which means a variable called context , not the context itself ( _context is a special variable name used to access the context in the template, but it does not appear in the context array sent for the function because it is the array itself).

Perhaps there is a way to accomplish this with a special compilation of the function by changing the node class. but I haven’t tried, and it may be a little harder to keep the semantic expression.
In general, I would recommend not writing such a function. Variable assignment in Twig does not have a semantic function and cannot be done as part of an expression (functions can be used in expressions, of course). Changing this semantics can lead to strange behavior.

+4
source

Like @DarkBee mentioned in his comment, you can change the context by passing it via the link:

 function setContextVar(&$context, ...) 

However, adding only the Twig function does not work (I am using Twig 2.4.4):

 $twig->addFunction(new Twig_Function('setContextVar', function(&$context, $name, $value) { $context[$name] = $value; }, ['needs_context' => true])); 

When you use a function in a Twig file, the context does not change, and you get this warning:

A warning. Parameter 1 - {closure} () is expected as a link, the value is given in C: \ ... \ vendor \ twig \ twig \ lib \ Twig \ Environment.php (378): eval () 'd code on line ...

Instead, you need to create a Twig extension:

 $twig->addExtension(new class extends Twig_Extension { public function getFunctions() { return [ new Twig_Function('setContextVar', [$this, 'setContextVar'], ['needs_context' => true]), ]; } public function setContextVar(&$context, $name, $value) { $context[$name] = $value; } }); 

Then you can use it in Twig without warning:

 {{ dump() }} {% do setContextVar('foo', 'bar') %} {{ dump() }} 

The above prints, for example:

 array(0) { } array(1) { ["foo"]=> string(3) "bar" } 
+1
source

All Articles