Pythonデコレータに相当するPHP?
質問
PHP関数を別の関数でラップできるようにしたいのですが、元の名前/パラメーターリストはそのままにしておきます。
たとえば:
function A() {
print "inside A()\n";
}
function Wrap_A() {
print "Calling A()\n";
A();
print "Finished calling A()\n";
}
// <--- Do some magic here (effectively "A = Wrap_A")
A();
出力:
Calling A()
inside A()
Finished calling A()
他のヒント
これは、PHPでPythonのデコレータを模倣する私の方法です。
function call_decorator ($decorator, $function, $args, $kwargs) {
// Call the decorator and pass the function to it
$decorator($function, $args, $kwargs);
}
function testing ($args, $kwargs) {
echo PHP_EOL . 'test 1234' . PHP_EOL;
}
function wrap_testing ($func, $args, $kwargs) {
// Before call on passed function
echo 'Before testing';
// Call the passed function
$func($args, $kwargs);
// After call on passed function
echo 'After testing';
}
// Run test
call_decorator('wrap_testing', 'testing');
出力:
Before testing
testing 1234
After testing
この実装では、匿名関数を使用して次のようなこともできます。
// Run new test
call_decorator('wrap_testing', function($args, $kwargs) {
echo PHP_EOL . 'Hello!' . PHP_EOL;
});
出力:
Before testing
Hello!
After testing
そして最後に、あなたがそんなに傾いているなら、このようなことさえすることができます。
// Run test
call_decorator(function ($func, $args, $kwargs) {
echo 'Hello ';
$func($args, $kwargs);
}, function($args, $kwargs) {
echo 'World!';
});
出力:
Hello World!
上記のこの構成により、必要に応じて変数を内部関数またはラッパーに渡すことができます。匿名の内部関数を使用した実装は次のとおりです。
$test_val = 'I am accessible!';
call_decorator('wrap_testing', function($args, $kwargs){
echo $args[0];
}, array($test_val));
匿名関数がなくてもまったく同じように動作します:
function test ($args, $kwargs) {
echo $kwargs['test'];
}
$test_var = 'Hello again!';
call_decorator('wrap_testing', 'test', array(), array('test' => $test_var));
最後に、ラッパーまたはラップパイ内の変数を変更する必要がある場合は、参照によって変数を渡すだけです。
参照なし:
$test_var = 'testing this';
call_decorator(function($func, $args, $kwargs) {
$func($args, $kwargs);
}, function($args, $kwargs) {
$args[0] = 'I changed!';
}, array($test_var));
出力:
testing this
参照あり:
$test_var = 'testing this';
call_decorator(function($func, $args, $kwargs) {
$func($args, $kwargs);
}, function($args, $kwargs) {
$args[0] = 'I changed!';
// Reference the variable here
}, array(&$test_var));
出力:
I changed!
これで今のところすべてです。多くの場合非常に便利です。必要に応じて複数回ラップすることもできます。
call_user_func_array
を探している可能性があります:
function wrapA() {
$args = func_get_args();
return call_user_func_array('A', $args);
}
PHP 5.3以降では、次のように言うこともできます。
return call_user_func_array('A', func_get_args());
質問を編集した後、いいえ、これは不可能ですが、いくつかの方法があります。この質問を参照してください: PHPでデコレータを実装する方法は?
PHPの関数を使用してこれを行うことはできません。 PerlやRubyなどの他の動的言語では、以前に定義した関数を再定義できますが、PHPで再定義しようとすると致命的なエラーがスローされます。
5.3では、匿名関数を作成して保存できます変数でそれ:
<?php
$my_function = function($args, ...) { ... };
$copy_of_my_function = $my_function;
$my_function = function($arg, ...) { /* Do something with the copy */ };
?>
別の方法として、従来のデコレータパターンやファクトリを使用して、代わりにクラスを操作することもできます。
所属していません StackOverflow