2016-01-22 13 views
5

Tôi đang cố gắng thực hiện đóng cửa nằm bên trong một mảng trên mẫu Twig. Dưới đây bạn có thể thấy một đoạn đơn giản mà tôi đang cố gắng:Thực hiện đóng cửa trên 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 %} 

Khi cành ám chỉ rằng mẫu, ném một ngoại lệ phàn nàn về một mảng chuỗi chuyển đổi

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 » 

Tôi sẽ đánh giá cao sự trợ giúp của bạn.

Cảm ơn!

Trả lời

1

Bạn không thể trực tiếp thực hiện đóng cửa bên trong mẫu Twig của bạn. Tuy nhiên, nếu bạn cần gọi một số PHP bên trong mẫu của bạn, bạn nên sử dụng create a Twig Extension và bao gồm logic của bạn bên trong.

+0

Cảm ơn! Nhưng giải pháp này không làm việc cho tôi vì logic là biến số – Carles

+0

Bạn có ý nghĩa gì bởi "logic là biến"? – Terenoth

+0

Có thể có nhiều hàm điều kiện khác nhau, với các điều kiện khác nhau. Tôi cho rằng đó không phải là hiệu quả để đặt nhiều phần mở rộng như các điều kiện khác nhau bởi vì nó sẽ giết hiệu suất trên khuôn mẫu rendering. – Carles

1

Cành không cho phép thực hiện việc này trực tiếp. Bạn có thể thêm chức năng đơn giản vào Twig để xử lý việc đóng cửa hoặc đóng bao đóng trong lớp để có thể sử dụng chức năng thuộc tính của Twig (vì gọi trực tiếp attribute(_context, 'myclosure', args) sẽ kích hoạt Lỗi nghiêm trọng vì Twig sẽ trả lại kết thúc trực tiếp và bỏ qua các đối số đã cho từ _context là một mảng).


Một tiện ích Twig đơn giản đạt được mục đích này sẽ trông giống như thế này cho Symfony 2.8+. (Đối với Symfony 4, xem 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'; 
    } 
} 

Sau đó, trong các mẫu của bạn, bạn chỉ cần phải gọi thực hiện:

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

Nếu không kéo dài cành, một cách để có được xung quanh vấn đề này là sử dụng một lớp đóng vai trò như một trình bao bọc cho việc đóng của bạn và sử dụng hàm attribute của Twig vì nó có thể được sử dụng để gọi một phương thức của một đối tượng.

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

Sau đó, bạn chỉ cần cho một trường hợp ClosureWrapper cho mẫu của bạn khi vẽ thay vì việc đóng cửa chính nó:

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

    ... 

Cuối cùng, trong mẫu của bạn, bạn cần phải sử dụng attribute để thực hiện việc đóng cửa bạn định nghĩa trong điều khiển của bạn:

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

Tuy nhiên, đây là một chút dư thừa như, internally, các attribute chức năng của Twig cũng giải thích các đối số đã cho. Bằng cách sử dụng mã trên, đối với mỗi cuộc gọi, các đối số được giải nén liên tục, đóng gói và giải nén lại.

Các vấn đề liên quan