PHP相当于一个python装饰器?

Fra*_*rth 11 php python function decorator wrapper

我希望能够通过另一个函数包装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();
Run Code Online (Sandbox Code Playgroud)

输出:

Calling A()
inside A()
Finished calling A()
Run Code Online (Sandbox Code Playgroud)

Zed*_*Zed 8

显然runkit可能对你有所帮助.

此外,您始终可以通过OO方式执行此操作.把原来的乐趣放在一个类中,把装饰器放到一个扩展类中.实例化并去.


Dbe*_*azy 7

这是我在 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');
Run Code Online (Sandbox Code Playgroud)

输出:

Before testing
testing 1234
After testing
Run Code Online (Sandbox Code Playgroud)

使用此实现,您还可以使用匿名函数执行以下操作:

// Run new test
call_decorator('wrap_testing', function($args, $kwargs) {
    echo PHP_EOL . 'Hello!' . PHP_EOL;
});
Run Code Online (Sandbox Code Playgroud)

输出:

Before testing
Hello!
After testing
Run Code Online (Sandbox Code Playgroud)

最后,如果您愿意,您甚至可以做这样的事情。

// Run test
call_decorator(function ($func, $args, $kwargs) {
    echo 'Hello ';
    $func($args, $kwargs);
}, function($args, $kwargs) {
    echo 'World!';
});
Run Code Online (Sandbox Code Playgroud)

输出:

Hello World!
Run Code Online (Sandbox Code Playgroud)

通过上面的这种构造,您可以将变量传递给内部函数或包装器,如果需要的话。这是具有匿名内部函数的实现:

$test_val = 'I am accessible!';

call_decorator('wrap_testing', function($args, $kwargs){
    echo $args[0];
}, array($test_val));
Run Code Online (Sandbox Code Playgroud)

如果没有匿名函数,它将完全相同:

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

$test_var = 'Hello again!';

call_decorator('wrap_testing', 'test', array(), array('test' => $test_var));
Run Code Online (Sandbox Code Playgroud)

最后,如果您需要修改包装器或包装器中的变量,您只需要通过引用传递变量。

没有参考:

$test_var = 'testing this';
call_decorator(function($func, $args, $kwargs) {
    $func($args, $kwargs);
}, function($args, $kwargs) {
    $args[0] = 'I changed!';
}, array($test_var));
Run Code Online (Sandbox Code Playgroud)

输出:

testing this
Run Code Online (Sandbox Code Playgroud)

供参考:

$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));
Run Code Online (Sandbox Code Playgroud)

输出:

I changed!
Run Code Online (Sandbox Code Playgroud)

这就是我现在所拥有的,它在很多情况下非常有用,如果您愿意,您甚至可以将它们包装多次。