2015-09-11 12 views
5

È possibile modificare il contesto corrente della rametta richiamando una Twig_SimpleFunction?Può una Twig_SimpleFunction modificare il contesto?

Ho la funzione qui sotto registrata:

<?php 
namespace Craft; 

class TwiggedTwigExtension extends \Twig_Extension 
{ 
    public function getName() 
    { 
     return 'Twigged'; 
    } 

    public function getFunctions() 
    { 
     return array(
      'setContextVar' => new \Twig_SimpleFunction('setContextVar', array($this, 'setContextVar'), array('needs_context' => true)), 
     ); 
    } 

    public function setContextVar($context, $str, $val) 
    { 
     $context['context'][$str] = $val; 

     var_dump(array_keys($context['context'])); 
    } 
} 

quando chiamato da un modello in questo modo {{ setContextVar('hellow', 'world') }}, il var_dump mostra il contesto modificato. Ma un rapido controllo nel modello come {{ dump(_context|keys) }} non mostra il contesto modificato.

Sto andando su questo nel modo sbagliato?

+0

hai definito correttamente la funzione con i parametri 'need_context' come descritto [qui] (http://twig.sensiolabs.org/doc/advanced.html#context-aware-filters)? – Matteo

+0

Sì, lo credo. Ecco un pastebin - http://pastebin.com/D8ZnKKWm – Fyrebase

risposta

4

Questo non è possibile con le funzioni perché il contesto non viene passato per riferimento.

Nel proprio interno, è sono anche accedendo $context['context'], il che significherebbe una variabile denominata context, non il contesto stesso (_context è un nome di variabile speciale utilizzato per accedere al contesto nel modello, ma non appare nel contesto array inviato per funzionare in quanto è la matrice stessa).

Potrebbe esserci un modo per eseguire questa operazione con una compilazione personalizzata della funzione cambiando la classe del nodo. ma non l'ho provato e potrebbe risultare un po 'difficile mantenere l'espressione semantica.
E comunque, consiglierei di non scrivere tale funzione. Assegnare una variabile in Twig non ha una funzione semantica e non può essere eseguita come parte di un'espressione (le funzioni sono utilizzabili nelle espressioni, ovviamente). Cambiare questa semantica può portare a comportamenti strani.

+0

Grazie a @ris. Ho rinunciato a questo approccio quando sono arrivato alla conclusione che era l'approccio sbagliato. – Fyrebase

+0

È possibile passare il contesto per riferimento cambiando la definizione della funzione in 'function setContextVar (& $ context, ...) "così ora è possibile modificare il contesto del ramoscello. Vedi [qui] (http://stackoverflow.com/questions/43978499/set-value-of-single-object-in-multidimensional-array-in-twig-template?noredirect=1#comment74986325_43978499) – DarkBee

1

Come @DarkBee citato nel suo commento, è possibile modificare il contesto passando per riferimento:

function setContextVar(&$context, ...) 

Tuttavia, aggiungendo solo una funzione di Twig non sembra funzionare (sto usando Twig 2.4.4):

$twig->addFunction(new Twig_Function('setContextVar', function(&$context, $name, $value) { 
    $context[$name] = $value; 
}, ['needs_context' => true])); 

Quando si utilizza la funzione in un file Ramoscello, il contesto non ottiene modificato, e si ottiene questo avvertimento:

Avviso: il parametro da 1 a {chiusura}() dovrebbe essere un riferimento, valore indicato in C: \ ... \ vendor \ twig \ twig \ lib \ Twig \ Environment.php (378): eval() ' d code on line ...

Invece, è necessario creare un'estensione Twig:

$twig->addExtension(new class extends Twig_Extension { 
    public function getFunctions() { 
     return [ 
      new Twig_Function('setContextVar', [$this, 'setContextVar'], ['needs_context' => true]), 
     ]; 
    } 

    public function setContextVar(&$context, $name, $value) { 
     $context[$name] = $value; 
    } 
}); 

Quindi è possibile utilizzare in Twig senza ottenere un avvertimento:

{{ dump() }} 
{% do setContextVar('foo', 'bar') %} 
{{ dump() }} 

Il stampe sopra ad es .:

array(0) { 
} 

array(1) { 
    ["foo"]=> 
    string(3) "bar" 
} 
Problemi correlati