1

状況は次のとおりです。

{% 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が参照によって変数を渡さないことを理解している限り、これを行う方法はありますか?

私が欲しいのは、アクション関数に渡される変数を変更することだけです。

ありがとう...

4

3 に答える 3

1

Twig関数は、常に参照によってオブジェクトに渡されます。各エントリを表すために、配列の代わりにオブジェクトを使用することを検討してください。

于 2014-01-06T20:33:01.793 に答える
1

私はあなたの問題の解決策があるかもしれません。Twigを使用してWordpressテーマを開発していて、参照によって変数を渡し、それらにいくつかのデータを追加したいと思いました。私の目標はこのようなものを作ることでした

{{ load_data('all_posts',foo) }}

そして、という名前の関数を実行し、load_all_postsこの関数の結果を割り当てたいと思いましたfoo(2番目の引数として渡した小枝変数)。また、私は次のものも機能するようにしたかった:

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

次のことを行うには、2つのことを行う必要があります。

  • 「ロード」トークンを作成します
  • 正しい関数を呼び出し、正しい場所にデータをロードします

トークンパーサーの作成:

トークンの作成は簡単です。次のクラスでこのトークンを解析する方法をtwigに指示する必要があります。

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

現在、アレイでのみ機能します。オブジェクト内にデータを読み込もうとすると、例外がスローされます。後で編集して、オブジェクトのサポートを追加します。これがあなたや他の人々に役立つことを願っています。良い1日を :)

于 2016-01-08T13:48:38.897 に答える
0

連想配列を単純なクラスインスタンスに置き換えると、問題ありません。

class Entry {
    public $title;
    // other properties possible
    __construct($title) {
        $this->title = $title
    }
}

その$entries場合、配列ではなくオブジェクトであるため、任意の関数への参照として渡されるEntryインスタンスの配列になります。その場合、元の小枝コードスニペットは問題なく(完全な構文)、タイトルが変更されます。

于 2021-10-20T15:45:59.327 に答える