11


5

PHP関数を別の関数でラップできるようにしたいのですが、元の名前/パラメータリストはそのまま残します。

例えば:

関数A(){print A()の内側\ n "; }

関数Wrap_A(){print "A()の呼び出し\ n"; A(); "A()の呼び出しを終了しました。\ n";を印刷してください。 }

// <--- Do some magic here (effectively "A = Wrap_A")

A();

出力:

A()内でA()を呼び出すA()の呼び出しを終了しました

4 Answer


7


どうやら runkitはhttp://php.net/manual/en/function.runkit-function-redefine.php[help]かもしれません。

また、あなたはいつもこれをオブジェクト指向の方法で行うことができます。 元の楽しさをクラスに入れ、デコレータを拡張クラスに入れます。 インスタンス化して行きます。


3


これは私がphpでpythonからデコレータを模倣する方法です。

function call_decorator($ decorator、$ function、$ args、$ kwargs){

//デコレータを呼び出して関数を渡します$ decorator($ function、$ args、$ kwargs); }

関数テスト($ args、$ kwargs){echo PHP_EOL。 'テスト1234'。 PHP_EOL; }

関数wrap_testing($ func、$ args、$ kwargs){

//呼び出し前に渡された関数echo 'Before testing';

//渡された関数を呼び出します$ func($ args、$ kwargs);

//呼び出し後、渡された関数echo 'After testing'; }

// Run test
call_decorator( 'wrap_testing'、 'testing');

出力:

テストをテストする前に1234テストをした後

この実装では、無名関数を使ってこのようなことをすることもできます。

// Run new test
call_decorator( 'wrap_testing'、function($ args、$ kwargs){echo PHP_EOL。 'こんにちは!' 。 PHP_EOL; ;));

出力:

テストする前にこんにちは! テスト後

そして最後に、もしあなたがそのように傾いていれば、あなたもこのようなことをすることさえできます。

// Run test
call_decorator(function($ func、$ args、$ kwargs){echo 'こんにちは; $ func($ args、$ kwargs);}、function($ args、$ kwargs){echo' World! '});

出力:

"こんにちは世界"

上記のこの構造で、必要ならば、内側の関数またはラッパーに変数を渡すことができます。 これは、無名の内部関数を使った実装です。

$ test_val = '私はアクセス可能です!';

call_decorator( 'wrap_testing'、関数($ args、$ kwargs){echo $ args [0];}、配列($ test_val));

無名関数がなくてもまったく同じように動作します。

function test($ args、$ kwargs){echo $ kwargs ['test']; }

$ test_var = 'こんにちはまた!';

call_decorator( 'wrap_testing'、 'test'、array()、array( 'test' => $ test_var));

最後に、ラッパーまたはラッパーのいずれかの内部で変数を変更する必要がある場合は、参照によって変数を渡すだけで済みます。

参照なしで:

$ test_var = 'これをテスト中'; call_decorator(関数($ func、$ args、$ kwargs){$ func($ args、$ kwargs);}、function($ args、$ kwargs){$ args [0] = '変更しました。 ($ test_var));

出力:

これをテストする

参照して:

$ test_var = 'これをテスト中'; call_decorator(function($ func、$ args、$ kwargs){$ func($ args、$ kwargs);}、function($ args、$ kwargs){$ args [0] = '変更しました。

// Reference the variable here
配列(

出力:

私が変更され!

私が今持っていることはそれだけです、それは多くの場合にかなり便利です、そしてあなたが望むならあなたはそれらを複数回ラップすることさえできます。


1


http://php.net/call_user_func_array[`call_user_func_array`]を探しているのかもしれません。
関数wrapA(){$ args = func_get_args(); call_user_func_array( 'A'、$ args)を返します。 }

PHP 5.3以降では、次のようにさえ言えるでしょう。

call_user_func_array( 'A'、func_get_args())を返します。

'' '' '

あなたの質問を編集した後、私は言うだろう、いいえ、これは不可能ですが、いくつかの方法があります、この質問を参照してください。 in-php [PHPでデコレータを実装する方法?]


1


PHPの関数でこれを行うことはできません。 PerlやRubyなどの他の動的言語では、以前に定義された関数を再定義することができますが、それを試みるとPHPは致命的なエラーをスローします。

5.3では、 匿名関数を作成して変数に格納することができます。


あるいは、伝統的なデコレータパターンやファクトリを使ってクラスを操作することもできます。