2016-01-22 8 views
5

पर बंद करने का निष्पादन मैं एक बंदरगाह टेम्पलेट पर एक सरणी के अंदर रहने वाले बंद को निष्पादित करने का प्रयास कर रहा हूं। नीचे आप एक सरल टुकड़ा मिल सकता है जिनमें से मैं कोशिश कर रहा हूँ:ट्विग


//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 %} 

टहनी टेम्पलेट renders है, एक अपवाद स्ट्रिंग रूपांतरण

करने के लिए एक सरणी के बारे में शिकायत फेंकता
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 » 

मैं आपकी मदद की सराहना करता हूं।

धन्यवाद!

उत्तर

1

आप सीधे अपने ट्विग टेम्पलेट के अंदर बंद नहीं कर सकते हैं। हालांकि, अगर आपको अपने टेम्पलेट के अंदर कुछ PHP कॉल करने की आवश्यकता है, तो आपको create a Twig Extension का उपयोग करना चाहिए और अपना तर्क अंदर शामिल करना चाहिए।

+0

धन्यवाद! लेकिन यह समाधान मेरे लिए काम नहीं करता है क्योंकि तर्क परिवर्तनीय है – Carles

+0

"तर्क परिवर्तनीय है" से आपका क्या मतलब है? – Terenoth

+0

यह विभिन्न स्थितियों के साथ कई अलग-अलग सशर्त कार्यों हो सकता है। मुझे लगता है कि अलग-अलग सशर्त के रूप में कई जुड़वां एक्सटेंशन डालने में सक्षम नहीं है क्योंकि यह टेम्पलेट प्रतिपादन पर प्रदर्शन को मार देगा। – Carles

1

ट्विग इसे सीधे करने की अनुमति नहीं देता है। आप या तो बंद करने के निष्पादन को संभालने के लिए टवीग में एक साधारण फ़ंक्शन जोड़ सकते हैं या टवीग के एट्रिब्यूट फ़ंक्शन का उपयोग करने में सक्षम होने के लिए कक्षा में अपना बंदरगाह लपेट सकते हैं (क्योंकि सीधे attribute(_context, 'myclosure', args) पर कॉल करने से घातक त्रुटि ट्रिगर हो जाएगी क्योंकि टिग सीधे बंद हो जाएगा और दिए गए तर्कों को अनदेखा करें क्योंकि _context एक सरणी है)।


इस उद्देश्य को प्राप्त करने वाला एक सरल टवीग एक्सटेंशन सिम्फनी 2.8+ के लिए ऐसा दिखाई देगा।

// 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 4 के लिए, new documentation देखें), तो आप बस कॉल करनी होगी निष्पादित करें:

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

टहनी विस्तार के बिना, एक ही रास्ता है इस समस्या को हल पाने के लिए एक वर्ग का उपयोग करना है जो आपके बंद होने के लिए एक रैपर के रूप में कार्य करता है और attribute टवीग के फ़ंक्शन का उपयोग करने के लिए उपयोग करता है क्योंकि इसका उपयोग ऑब्जेक्ट की विधि को कॉल करने के लिए किया जा सकता है।

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

फिर, आप बस जब बंद ही के बजाय प्रतिपादन अपने टेम्पलेट के लिए एक ClosureWrapper उदाहरण देने के लिए की जरूरत है:

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

    ... 

अंततः, अपने खाके में, आप attribute उपयोग करने के लिए बंद करने पर अमल करने की जरूरत है आप अपने नियंत्रक में परिभाषित:

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

हालांकि, इस के रूप में, internally थोड़ा निरर्थक है,टवीग के 10 कार्य दिए गए तर्कों को भी अनपैक करते हैं। उपरोक्त कोड का उपयोग करके, प्रत्येक कॉल के लिए, तर्क लगातार अनपॅक किए जाते हैं, पैक किए जाते हैं और फिर से अनपॅक किए जाते हैं।