Twig

2016-01-22 25 views
5

üzerinde kapatma yürütme Bir Twig şablonundaki bir dizinin içinde bulunan bir kapatma gerçekleştirmeye çalışıyorum. Eğer basitleştirilmiş parçacığını bulabiliriz Aşağıda hangi deniyorum:Twig


//Symfony controller 
... 
$funcs = array(
    "conditional" => function($obj){ 
     return $obj->getFoo() === $obj::TRUE_FOO 
    } 
); 
$this->render('template_name', array('funcs' => $funcs)); 

{# Twig template #} 
{# obj var is set #} 
... 
{% if funcs.conditional(obj)%} 
<p>Got it</p> 
{% endif %} 

Twig şablonu oluşturulduğunda, dize dönüştürme

bir Array şikayetçi bir istisna atar

An exception has been thrown during the rendering of a template ("Notice: Array to string conversion") in "template_name.html.twig". 
500 Internal Server Error - Twig_Error_Runtime 
1 linked Exception: ContextErrorException » 

Yardımlarınız için teşekkür ederiz.

Teşekkürler!

cevap

1

Dal şablonunuzun içinde doğrudan bir kapatma gerçekleştiremezsiniz. Bununla birlikte, eğer şablonunuzun içinde PHP'yi çağırmanız gerekiyorsa, create a Twig Extension'u kullanmalı ve mantığınızı içeriye dahil etmelisiniz.

+0

Teşekkürler! Fakat mantık değişkeni – Carles

+0

olduğu için bu çözüm benim için çalışmaz "Mantık değişkendir" ile ne demek istiyorsun? – Terenoth

+0

Farklı koşullara sahip birçok farklı koşullu işlev olabilir. Şablon oluşturmada performansı azaltacağından, farklı koşullara göre fazla sayıda uzantı koymanın etkili olmadığını düşünüyorum. – Carles

1

Twig doğrudan bunu yapmaya izin vermiyor. Twig'e basit bir işlev ekleyebilir veya kapağın işlevini kullanabilmeniz için kapağınızı bir sınıfa sarın ya da Twig'in öznitelik işlevini doğrudan kullanabileceğinden, doğrudan attribute(_context, 'myclosure', args)'u bir Önemli Hata tetikleyecektir. _context bir dizidir, çünkü verilen argümanları yok sayın).


Bu amaca ulaşan basit bir Twig uzantısı Symfony 2.8+ için buna benzer. sadece aramak zorunda şablonlarınızda, Sonra

// 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'; 
    } 
} 

(Symfony'de 4 için new documentation bakınız) yürütün:

{{ execute(closure, [argument1, argument2]) }} 

Twig uzanan olmadan, tek yönlü bu sorunu aşmanın Kapanışınız için bir sarıcı görevi gören bir sınıf kullanmak ve bir nesnenin yöntemini çağırmak için kullanılabileceği için Twig'in attribute işlevini kullanmaktır.

// 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()); 
    } 
} 

Sonra, sadece yerine kapağın kendisinin render yaparken şablona bir ClosureWrapper örneğini vermek gerekir: Şablonunuzdaki,

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]); 
    } 

    ... 

Sonunda, kapatma çalıştırmak için attribute kullanmak gerekir Eğer denetleyici tanımlanan:

// Displays 12 
{{ attribute(closure, 'execute', [4, 6]) }} 

Ancak bu, gibi biraz gereksiz Twig'in 10 işlevi, verilen argümanları da açar. Yukarıdaki kodu kullanarak, her bir çağrı için, argümanlar art arda paketlenip paketlenip tekrar açılır.