Gałązka nie pozwala zrobić tego bezpośrednio. Możesz dodać prostą funkcję do Twiga, aby obsłużyć wykonanie zamknięć lub zamknąć swoje zamknięcie w klasie, aby móc użyć funkcji atrybutu Twig (ponieważ bezpośrednie wywołanie attribute(_context, 'myclosure', args)
spowoduje błąd krytyczny, ponieważ Twig zwróci zamknięcie bezpośrednio i zignoruj podane argumenty, ponieważ _context
jest tablicą).
Proste rozszerzenie Twig, które osiąga ten cel, będzie wyglądało tak w Symfony 2.8+. (Dla Symfony 4, zobacz 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';
}
}
Następnie w szablonach, wystarczy zadzwonić wykonać:
{{ execute(closure, [argument1, argument2]) }}
bez rozszerzania gałązka, jeden sposób, aby obejść ten problem jest użycie klasy, która działa jak opakowanie dla zamknięcia i używania funkcji Twig, ponieważ może być użyta do wywołania metody obiektu.
// 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());
}
}
Następnie wystarczy dać ClosureWrapper wystąpienie do szablonu podczas renderowania zamiast zamknięcia samego:
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]);
}
...
Ostatecznie w szablonie, trzeba użyć attribute
wykonać zamknięcie zdefiniowano w kontrolerze:
// Displays 12
{{ attribute(closure, 'execute', [4, 6]) }}
jest to jednak nieco zbędny jak internally The attribute
funkcji Twig rozpakowuje również podane argumenty. Używając powyższego kodu, dla każdego połączenia argumenty są sukcesywnie rozpakowywane, pakowane i rozpakowywane ponownie.
Dzięki! Ale to rozwiązanie nie działa dla mnie, ponieważ logika jest zmienna – Carles
Co rozumiesz przez "logika jest zmienna"? – Terenoth
Może to być wiele różnych funkcji warunkowych z różnymi warunkami. Uważam, że nie jest wydajne umieszczanie tylu rozszerzeń gałązek co innych warunkowych, ponieważ zabiłoby to wydajność podczas renderowania szablonu. – Carles