Twig does not allow you to do this directly. You can either add a simple Twig function to handle the execution of closures, or wrap the closure in the class to be able to use the Twig attribute function (since a direct call to attribute(_context, 'myclosure', args) causes Fatal Error, because Twig will return the closure directly and ignore these arguments since _context is an array).
A simple Twig extension that accomplishes this will look like this for Symfony 2.8+. (For symfony 4 see new documentation )
// src/AppBundle/Twig/Extension/CoreExtensions.php namespace AppBundle\Twig\Extension; class CoreExtensions extends \Twig_Extension { public function getFunctions() { return [ new \Twig_SimpleFunction('execute', [$this, 'executeClosure']) ]; } public function executeClosure(\Closure $closure, $arguments) { return $closure(...$arguments); } public function getName() { return 'core_extensions_twig_extension'; } }
Then in your templates you just need to call execute:
{{ execute(closure, [argument1, argument2]) }}
Without the Twig extension, one way around this problem is to use a class that acts as a wrapper for your closure and use the attribute the Twig function, since it can be used to call an object's method.
// src/AppBundle/Twig/ClosureWrapper.php namespace AppBundle\Twig; /** * Wrapper to get around the issue of not being able to use closures in Twig * Since it is possible to call a method of a given object in Twig via "attribute", * the only purpose of this class is to store the closure and give a method to execute it */ class ClosureWrapper { private $closure; public function __construct($closure) { $this->closure = $closure; } public function execute() { return ($this->closure)(...func_get_args()); } }
Then you just need to provide an instance of ClosureWrapper for your template when rendering instead of closing itself:
use AppBundle\Twig\ClosureWrapper; class MyController extends Controller { public function myAction() { $localValue = 2; $closure = new ClosureWrapper(function($param1, $param2) use ($localValue) { return $localValue + $param1 + $param2; }); return $this->render('mytemplate.html.twig', ['closure' => $closure]); } ...
In the end, in your template, you need to use attribute to execute the closure that you defined in your controller:
// Displays 12 {{ attribute(closure, 'execute', [4, 6]) }}
However, this is a bit redundant, because internally , the attribute Twig function also decompresses these arguments. Using the code above, for each call, the arguments are sequentially unpacked, packed, and unpacked again.