Php calling object function

call_user_func

Calls the callback given by the first parameter and passes the remaining parameters as arguments.

Parameters

Zero or more parameters to be passed to the callback.

Note:

Note that the parameters for call_user_func() are not passed by reference.

Example #1 call_user_func() example and references

$a = 0 ;
call_user_func ( ‘increment’ , $a );
echo $a . «\n» ;

// it is possible to use this instead
call_user_func_array ( ‘increment’ , array(& $a ));
echo $a . «\n» ;

// it is also possible to use a variable function
$increment = ‘increment’ ;
$increment ( $a );
echo $a . «\n» ;
?>

The above example will output:

Warning: Parameter 1 to increment() expected to be a reference, value given in … 0 1 2

Return Values

Returns the return value of the callback.

Examples

Example #2 call_user_func() example

function barber ( $type )
echo «You wanted a $type haircut, no problem\n» ;
>
call_user_func ( ‘barber’ , «mushroom» );
call_user_func ( ‘barber’ , «shave» );
?>

The above example will output:

You wanted a mushroom haircut, no problem You wanted a shave haircut, no problem

Example #3 call_user_func() using namespace name

class Foo static public function test () print «Hello world!\n» ;
>
>

call_user_func ( __NAMESPACE__ . ‘\Foo::test’ );
call_user_func (array( __NAMESPACE__ . ‘\Foo’ , ‘test’ ));

The above example will output:

Example #4 Using a class method with call_user_func()

class myclass static function say_hello ()
echo «Hello!\n» ;
>
>

call_user_func (array( $classname , ‘say_hello’ ));
call_user_func ( $classname . ‘::say_hello’ );

call_user_func (array( $myobject , ‘say_hello’ ));

The above example will output:

Example #5 Using lambda function with call_user_func()

The above example will output:

Notes

Note:

Callbacks registered with functions such as call_user_func() and call_user_func_array() will not be called if there is an uncaught exception thrown in a previous callback.

See Also

  • call_user_func_array() — Call a callback with an array of parameters
  • is_callable() — Verify that a value can be called as a function from the current scope.
  • Variable functions
  • ReflectionFunction::invoke() — Invokes function
  • ReflectionMethod::invoke() — Invoke

User Contributed Notes 31 notes

I benchmarked the comparison in speed between variable functions, call_user_func, and eval. My results are below:

Variable functions took 0.125958204269 seconds.
call_user_func took 0.485446929932 seconds.
eval took 2.78526711464 seconds.

This was run on a Compaq Proliant server, 180MHz Pentium Pro 256MB RAM. Code is as follows:

function fa () < return 1 ; >
function fb () < return 1 ; >
function fc ()

$calla = ‘fa’ ;
$callb = ‘fb’ ;
$callc = ‘fc’ ;

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
$x += $calla ();
$x += $callb ();
$x += $callc ();
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «Variable functions took » . ( microtime ( true ) — $time ) . » seconds.
» );

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
$x += call_user_func ( ‘fa’ , » );
$x += call_user_func ( ‘fb’ , » );
$x += call_user_func ( ‘fc’ , » );
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «call_user_func took » . ( microtime ( true ) — $time ) . » seconds.
» );

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
eval( ‘$x += ‘ . $calla . ‘();’ );
eval( ‘$x += ‘ . $callb . ‘();’ );
eval( ‘$x += ‘ . $callc . ‘();’ );
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «eval took » . ( microtime ( true ) — $time ) . » seconds.
» );

if you simply want to dynamically call a method on an object it is not necessary to use call_user_function but instead you can do the following:

?>

I’ve used the above so I know it works.

@insta at citiesunlimited dot com & @Maresa

call_user_func() alleged slowness is quite over estimated when it comes to real use cases. we are talking about loosing fraction of a second every million calls, which by the way would take less than half a sec to execute in the worst case.

I don’t know of many processes that would actually suffer from this kind of overhead.

Iterations: 100 000
Averaged over: 10
PHP 5.6.30 (cli) (built: Jan 18 2017 19:47:28)
Overall Average
+————————+———-+————+———+
| Invocation | Time (s) | Delta (s) | % |
+————————+———-+————+———+
| directFunction | 0.0089 | -0.0211 | -70.19 |
| directStatic | 0.0098 | -0.0202 | -67.39 |
| directLambda | 0.0109 | -0.0191 | -63.52 |
| directInstance | 0.0116 | -0.0184 | -61.31 |
| directClosure | 0.0150 | -0.0150 | -50.15 |
| Invoke | 0.0282 | -0.0018 | -6.13 |
| call_user_func | 0.0300 | | |
| ClosureFactory | 0.0316 | +0.0016 | +5.20 |
| assignedClosureFactory | 0.0328 | +0.0028 | +9.28 |
| call_user_func_array | 0.0399 | +0.0099 | +33.02 |
| InvokeCallUserFunc | 0.0418 | +0.0118 | +39.17 |
| directImplementation | 0.0475 | +0.0175 | +58.28 |
+————————+———-+————+———+

Iterations: 100 000
Averaged over: 10
PHP 7.1.2 (cli) (built: Feb 14 2017 21:24:45)
Overall Average
+————————+———-+————+———+
| Invocation | Time (s) | Delta (s) | % |
+————————+———-+————+———+
| directFunction | 0.0043 | -0.0096 | -68.92 |
| directStatic | 0.0050 | -0.0089 | -64.04 |
| directInstance | 0.0058 | -0.0081 | -58.22 |
| directLambda | 0.0063 | -0.0075 | -54.44 |
| directClosure | 0.0081 | -0.0058 | -41.57 |
| call_user_func | 0.0139 | | |
| call_user_func_array | 0.0147 | +0.0008 | +5.84 |
| Invoke | 0.0187 | +0.0048 | +34.61 |
| ClosureFactory | 0.0207 | +0.0069 | +49.43 |
| assignedClosureFactory | 0.0219 | +0.0080 | +57.75 |
| directImplementation | 0.0232 | +0.0094 | +67.53 |
| InvokeCallUserFunc | 0.0264 | +0.0126 | +90.67 |
+————————+———-+————+———+

A good use for call_user_func(); is for recursive functions.
If you’re distributing code, you will often come across users who will rename functions and break the code..
Use this: call_user_func(__FUNCTION__, . ); inside a function to call itself with whatever parameters you want.

// example, an extremely simplified factorial calculator..
// it’s quite obvious when someone renames the function, it’ll spit out an error because it wants to call itself.
function Factorial ( $i = 1 ) return( $i == 1 ? 1 : $i * Factorial ( $i — 1 ));
>

// you can give this function whatever name you want, it’ll always work, of course if you initially call it using the name you gave it.
function qwertyuiop ( $i = 1 ) return( $i == 1 ? 1 : $i * call_user_func ( __FUNCTION__ , $i — 1 ));
>
?>

Just that I didn’t see any reference to recursive functions when user_call_func(); really helps.

You don’t need to use this function to call a variable class function. Instead you can do the following:

The example works in PHP 5 from within the class. It is the <> that do the trick.

Updating «insta at citiesunlimited dot com»‘s benchmarking for PHP 7.1.17 we have an INVERSION of results between using variables and call_user_func():

Variable functions took 0.0020599365234375 seconds.
call_user_func took 0.00094509124755859 seconds.
eval took 0.024421215057373 seconds.

So, call_user_func() is now actually the way to go in PHP 7.1+.

function fa () < return 1 ; >
function fb () < return 1 ; >
function fc ()

$calla = ‘fa’ ;
$callb = ‘fb’ ;
$callc = ‘fc’ ;

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
$x += $calla ();
$x += $callb ();
$x += $callc ();
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «Variable functions took » . ( microtime ( true ) — $time ) . » seconds.
» );

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
$x += call_user_func ( ‘fa’ , » );
$x += call_user_func ( ‘fb’ , » );
$x += call_user_func ( ‘fc’ , » );
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «call_user_func took » . ( microtime ( true ) — $time ) . » seconds.
» );

$time = microtime ( true );
for( $i = 5000 ; $i —; ) $x = 0 ;
eval( ‘$x += ‘ . $calla . ‘();’ );
eval( ‘$x += ‘ . $callb . ‘();’ );
eval( ‘$x += ‘ . $callc . ‘();’ );
if( $x != 3 ) die( ‘Bad numbers’ );
>
echo( «eval took » . ( microtime ( true ) — $time ) . » seconds.
» );

public function hello ( $str )

[ $obj , ‘hello’ ]( ‘World’ ); // the array can be called as a function

>phil at gettcomm dot com
>22-May-2002 04:51
>if you need to get a reference back from a method, you can work around
>call_user_func()’s shortcomings like this:
>
Naaa! Having back a reference is a real problem, but it can be solved by mean of eval(), instead of using call_user_func:

class Node <
var $name ;
var $child ;
function Node ( $name ) < $this ->name = $name ; >
function & getChild () < return $this ->child ; >
>
$p = new Node ( ‘Father’ );
$c = new Node ( ‘Child’ );
$p -> child = & $c ;

eval ( «\\ $cref = &\\ $p -> getChild ();» );
$cref -> name = ‘Another Child’ ;

// Prints out ‘Another Child’
echo «****** After eval c keyword»>. $c -> name . «\\n\\n» ;

The previous note I posted had an error in the source code. That has been corrected in this note.

Note, that returning by reference does not work properly when the function
is called using call_user_func.

This example illustrates the problem.

print «result:» . $result . «
\n» ;
print «globalVar: » . $globalVar . «
\n» ;

print «result2: » . $result2 . «
\n» ;
print «globalVar: » . $globalVar . «
\n» ;
?>

The above code results in the following output .
Note that $result is not a reference to $globalVar.

result:0
globalVar: 0
result2: 3
globalVar: 3

Also, the use of call_user_method is now deprecated in favor of passing
array( &$object, $method ) as the function to call_user_func. This is
reported when error reporting is set to E_ALL in the latest versions of
PHP.

An entirely OO solution to add dynamicly methods to classes, I used in a project:
class ProductPart

protected $data ;
protected $plugins = array();
function __construct ( $data )

>
public function register ( ProductPlugin $plugin )

if(! in_array ( $plugin , $this -> plugins ))

$this -> plugins [ $plugin -> toString ()] = $plugin ;
> else throw new Exception ( ‘Function allready defined’ );
>
>
public function unregister ( ProductPlugin $plugin ) if(isset( $this -> plugins [ $plugin -> toString ()])) unset( $this -> plugins [ $plugin -> toString ()]);
> else throw new Exception ( ‘No such function’ );
>

protected function __call ( $method , $args ) if(isset( $this -> plugins [ $method ])) array_unshift (& $args , $this -> data );
array_unshift (& $args , $this );
return $this -> plugins [ $method ]-> run ( $args [ 0 ], $args [ 1 ], $args [ 2 ]);

> else throw new Exception ( ‘No such function’ );
>
>
> ?>

I simplified the class somewhat for clearity.

With this class, you can dynamicly add and remove classes by calling register or unregister. Register will store the object in an associative array by calling toString (as defined by ProductPlugin) and saving the method under the returned string in the array. (In this case the name of the method the class adds.)

When a method is called, which isn’t standard in the object, _call will lookup the called method in the array. If found, __call run the method of the plugin with the provided arguments. I restricted the user provided argument to 1, because I want to force the user to use associative arrays.

Because I chose an array to store my classes, removing a function is quite simple. However the unregister function isn’t optimal, I better pass a string instead of a plugin object. I didn’t test it yet on performance.

abstract class ProductPlugin protected $name = null ;
abstract public function run ( $obj , $data , $args );
public function __construct ( $data = null )

if( $this -> name === null ) throw new Exception ( ‘Name must be defined’ );
>
$this -> init ( $data );
>
protected function init ( $data )

>
public function toString () return $this -> name ;
>
>

?>

And at last some demonstration code:

$bla = new ProductPart (array( ‘HelloWorld’ => ‘Hello world’ ));
$hello = new helloPlugin ();
$bla -> register ( $hello );
$bla -> HelloWorld ();
$bla -> unregister ( $hello );
$bla -> HelloWorld ();

Источник

Читайте также:  K means example java
Оцените статью