PHP equivalent for a python decorator?

前端 未结 5 631
夕颜
夕颜 2020-12-29 09:04

I want to be able to wrap a PHP function by another function, but leaving its original name/parameter list intact.

For instance:

function A() {
    p         


        
5条回答
  •  爱一瞬间的悲伤
    2020-12-29 09:52

    Here is my method of mimicking decorators from python in php.

    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');
    

    Output:

    Before testing
    testing 1234
    After testing
    

    With this implementation you can also do something like this with an anonymous function:

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

    Output:

    Before testing
    Hello!
    After testing
    

    And lastly you can even do something like this, if you are so inclined.

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

    Output:

    Hello World!
    

    With this construction above, you can pass variables to the inner function or wrapper, if need be. Here is that implementation with an anonymous inner function:

    $test_val = 'I am accessible!';
    
    call_decorator('wrap_testing', function($args, $kwargs){
        echo $args[0];
    }, array($test_val));
    

    It will work exactly the same without an anonymous function:

    function test ($args, $kwargs) {
        echo $kwargs['test'];
    }
    
    $test_var = 'Hello again!';
    
    call_decorator('wrap_testing', 'test', array(), array('test' => $test_var));
    

    Lastly, if you need to modify the variable inside either the wrapper or the wrappie, you just need to pass the variable by reference.

    Without reference:

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

    Output:

    testing this
    

    With reference:

    $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));
    

    Output:

    I changed!
    

    That is all I have for now, it is a pretty useful in a lot of cases, and you can even wrap them multiple times if you want to.

提交回复
热议问题