情况如下:
{% for entry in entries %}
{{ action('entry_modify', entry) }}
{{ entry.title }}
{% endfor %}
action($action,$params)方法是为某个操作注册的插件的某种触发器。在这种情况下,我调用"entry_modify"操作,一个插件用数组"entry"参数来响应这个操作。
function plugin(&$params)
{
$params['title'] = 'changed to ...';
}
但据我所知,Twig不是通过引用传递变量的,有什么方法可以做到这一点吗?
我只想修改传递给action函数的变量。
谢谢。。。
我可能会为您的问题找到解决方案。我正在用Twig开发Wordpress主题,我想通过引用传递变量并向它们添加一些数据。我的目标是制作这样的
{{ load_data('all_posts',foo) }}
我想执行一个名为CCD_ 1的函数,并将该函数的结果分配给CCD_。此外,我希望以下内容也能发挥作用:
{% set foo = {'bar':'bar'} %}
{#foo is#}
array(1) {
["bar"]=>
string(3) "bar"
}
{{load_data('all_posts',foo.posts)}}
{#foo is#}
array(2) {
["bar"]=>
string(3) "bar"
["posts"]=>
array(3) {
[0]=>
string(5) "post1"
[1]=>
string(5) "post2"
[2]=>
string(5) "post3"
}
}
由于并非所有变量都是通过引用传递给函数的。我们不能将函数用于此目的。相反,我创建了自己的标签,并像这样使用:
{% set foo = {'bar':'bar'} %}
{% load all_pots in foo.posts %}
要做到以下几点,我们必须做两件事:
- 创建"加载"令牌
- 调用正确的函数并在正确的位置加载数据
正在创建令牌分析器:
令牌的创建很容易。我们只需要告诉trick如何使用以下类解析此令牌:
class Load_Data_TokenParser extends Twig_TokenParser
{
public function parse(Twig_Token $token)
{
$stream = $this->parser->getStream();
$variable_array = array(); //an array where we'll store the destination variable, as it can be just foo or foo.post, or foo.bar.foo.bar.posts
$function_name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //here we say that we expect a name. In our case it'll be 'all_posts' (the name of the function we will execute)
$in = $stream->expect(Twig_Token::OPERATOR_TYPE)->getValue(); //here we say that the next thing should be the operator 'in'
while(Twig_Token::typeToEnglish($stream->getCurrent()->getType()) === 'name'){ //and with this while, we get all the variable names that are separated with '.'
array_push($variable_array,$stream->getCurrent()->getValue());
$stream->next();
$new = $stream->getCurrent();
if(Twig_Token::typeToEnglish($new->getType()) === 'punctuation'){
$stream->next();
} else {
break;
}
}
//in our case $variable_array here will be ['foo','posts']
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new Load_Node($variable_array, $function_name, $token->getLine(), $this->getTag());
}
public function getTag()
{
return 'load';
}
}
最后,我们返回一个新的"Load_Node",并将行和当前标记传递给$variable_array, $function_name
。
正在加载数据
class Load_Node extends Twig_Node
{
public function __construct($variable_array, $function_name, $line, $tag = null)
{
$value = new Twig_Node();
parent::__construct(array('value'=>$value),array(
'variable_array'=>$variable_array,
'function_name'=>$function_name
),$line,$tag);
}
public function compile(Twig_Compiler $compiler)
{
$variable_access_string = '';
$variable_array = $this->getAttribute('variable_array');
foreach ($variable_array as $single_variable) {
$variable_access_string.= '['''.$single_variable.''']';
} //here we prepare the string that will be used to access the correct variables. In our case here $variable_access_string will be "['foo']['posts']"
$compiler
->addDebugInfo($this)
->write('$context'.$variable_access_string.' = load_'.$this->getAttribute('function_name').'()')
->raw(";'n"); //and the here we call load_{function_name} and assign the result to the correct variable
}
}
目前它只适用于数组。如果您试图在对象内部加载数据,它会引发异常。稍后我将对其进行编辑,并添加对对象的支持。我希望这将帮助你和其他人。祝你今天愉快:)
Twig函数总是通过引用传递对象。您可以考虑使用对象而不是数组来表示每个条目。
如果用一个简单的类实例替换关联数组,就可以了。
class Entry {
public $title;
// other properties possible
__construct($title) {
$this->title = $title
}
}
那么$entries
将是一个Entry实例数组,它将作为对任何函数的引用传递,因为它是一个对象,而不是数组。那么您的原始trick代码片段就可以了(完美的语法),并且可以修改标题。