PHP equivalent for python decorator?

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

For example:

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

Output:

 Calling A() inside A() Finished calling A() 
+7
function python php decorator wrapper
source share
4 answers

Apparently runkit can help you .

In addition, you can always do this in an OO way. Put the original fun in the classroom and the decorator in the extended classroom. Create and go.

+6
source share

maybe you are looking for call_user_func_array :

 function wrapA() { $args = func_get_args(); return call_user_func_array('A', $args); } 

since PHP 5.3 you can even say:

 return call_user_func_array('A', func_get_args()); 

after you edited your question, I would say no, this is not possible, but there are some ways, look at this question: how to implement a decorator in PHP?

+1
source share

You cannot do this with functions in PHP. In other dynamic languages, such as Perl and Ruby, you can override previously defined functions, but PHP throws a fatal error when you try to do this.

In 5.3, you can create an anonymous function and save it in a variable:

 <?php $my_function = function($args, ...) { ... }; $copy_of_my_function = $my_function; $my_function = function($arg, ...) { /* Do something with the copy */ }; ?> 

Alternatively, you can use the traditional decorator and / or factory pattern and work with classes instead.

+1
source share

Here is my method of imitating 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 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 finally, you can even do something like that if you are so addicted.

 // 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 an internal function or shell, if necessary. Here is this implementation with an anonymous internal 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)); 

Finally, if you need to change a variable inside a wrapper or wrapper, you just need to pass the variable by reference.

No 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 a link:

 $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's all I have at the moment, in many cases it is very useful, and you can even wrap them several times if you want.

+1
source share

All Articles