php7 calluserfuncarray,call_user_func()

call_user_func()

(PHP 4, PHP 5, PHP 7)

把第一个参数作为回调函数调用

说明call_user_func(callable$callback[,mixed$parameter[,mixed$...]]):mixed

第一个参数$callback是被调用的回调函数,其余参数是回调函数的参数。

参数$callback将被调用的回调函数(callable)。$parameter0个或以上的参数,被传入回调函数。Note:

请注意,传入call_user_func()的参数不能为引用传递。

Example #1call_user_func()的参考例子<?php

error_reporting(E_ALL);

function increment(&$var)

{

$var++;

}

$a = 0;

call_user_func('increment', $a);

echo $a."\n";

call_user_func_array('increment', array(&$a)); // You can use this instead before PHP 5.3

echo $a."\n";

?>

以上例程会输出:

0

1

返回值

返回回调函数的返回值。

更新日志版本说明5.3.0对面向对象里面的关键字的解析有所增强。在此之前,使用两个冒号来连接一个类和里面的一个方法,把它作为参数来作为回调函数的话,将会发出一个E_STRICT的警告,因为这个传入的参数被视为静态方法。

范例

Example #2call_user_func()的例子<?php

function barber($type)

{

echo "You wanted a$typehaircut, no problem\n";

}

call_user_func('barber', "mushroom");

call_user_func('barber', "shave");

?>

以上例程会输出:You wanted a mushroom haircut, no problem

You wanted a shave haircut, no problem

Example #3call_user_func()命名空间的使用<?php

namespace Foobar;

class Foo {

static public function test() {

print "Hello world!\n";

}

}

call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0

call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0

?>

以上例程会输出:Hello world!

Hello world!

用call_user_func()来调用一个类里面的方法<?php

class myclass {

static function say_hello()

{

echo "Hello!\n";

}

}

$classname = "myclass";

call_user_func(array($classname, 'say_hello'));

call_user_func($classname .'::say_hello'); // As of 5.2.3

$myobject = new myclass();

call_user_func(array($myobject, 'say_hello'));

?>

以上例程会输出:Hello!

Hello!

Hello!

把完整的函数作为回调传入call_user_func()<?php

call_user_func(function($arg) { print "[$arg]\n"; }, 'test'); /* As of PHP 5.3.0 */

?>

以上例程会输出:[test]

注释Note:

在函数中注册有多个回调内容时(如使用call_user_func()与call_user_func_array()),如在前一个回调中有未捕获的异常,其后的将不再被调用。

参见callback类型的信息

ReflectionFunction::invoke() Invokes function

ReflectionMethod::invoke() InvokeI 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 () { return 1; }

$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:

$method_name = "AMethodName";

$obj = new ClassName();

$obj->{$method_name}();

?>

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

Regards,

-- Greg@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 |

+------------------------+----------+-----------+--------+

If you want more details : https://github.com/fab2s/call_user_funcA 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.The "call_user_func() example and references" has become misleading since it will throw an exception starting from at least php 5.6.30:

// Parameter 1 to increment() expected to be a reference, value given

?>

The crash occurs when call_user_func() is called as it does not provide increment() with a reference.

Also note that :

call_user_func('increment', &$a);

?>

will also throw an exception :

// Call-time pass-by-reference has been removed

?>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){

$this->data = $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.

The ProductPlugin class:

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

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

$this->{$fnname}();

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

Regards,

Julian.I tested the same code that insta at citiesunlimited dot com pasted on the following machines:

www1 machine:

OS: FreeBSD 5.2.1-RELEASE

CPU: 2 x Intel(R) Xeon(TM) CPU 2.66GHz (2657.82-MHz 686-class CPU) with Hyperthreading

MEM: 1073217536 (1023 MB)

PHP 5.1.2 (cli)

PHP 4.4.1 (Web)

www2 machine:

OS: Linux version 2.6.14-gentoo-r5 Gentoo 3.4.3-r1, ssp-3.4.3-0, pie-8.7.7)

CPU: 2 x Dual Core AMD Opteron(tm) Processor 265 stepping 02 1808.357 MHz

MEM: 2060388k total

PHP 5.1.2 (cli)

PHP Version 4.4.0-pl1-gentoo (web)

dev machine:

OS: Linux version 2.6.15-gentoo-r1 Gentoo 3.3.5.20050130-r1, ssp-3.3.5.20050130-1, pie-8.7.7.1

CPU: Intel(R) Pentium(R) 4 CPU 2.00GHz stepping 04

MEM: 516384k total,

PHP 4.4.0-pl1-gentoo (cli)

PHP Version 4.4.0-pl1-gentoo (web)

The result are as follows:

www1 - CLI

Variable functions took 0.012186050415 seconds.

call_user_func took 0.0300550460815 seconds.

eval took 0.17235994339 seconds.

www1 - Web

Variable functions took 0.017616 seconds.

call_user_func took 0.034926 seconds.

eval took 0.149618 seconds

www2 - CLI

Variable functions took 0.0065491199493408 seconds.

call_user_func took 0.019452095031738 seconds.

eval took 0.10734891891479 seconds.

www2 - Web

Variable functions took 0.01565 seconds.

call_user_func took 0.02613 seconds.

eval took 0.132258 seconds.

dev - CLI

Variable functions took 0.025176 seconds.

call_user_func took 0.047402 seconds.

eval took 0.168196 seconds.

dev - Web

Variable functions took 0.025465 seconds.

call_user_func took 0.049713 seconds.

eval took 0.20154 seconds.

On www1 - CLI, eval is about 14 times slower than calling function by using variable.

On www1 - Web, eval is about 8.5 times slower (hmm interesting. Perhaps PHP4 is faster calculating eval than PHP5)

On www2 - CLI, eval is about 16 times slower than calling function by using variable.

On www2 - Web, eval is about 8.5 times slower (about same result as www1)

On dev - CLI, eval is about 6.6 times slower than calling function by using variable.

On dev - Web, eval is about 8 times slower (about same result as www1)

On the dev machine, CLI and web version of PHP is the same. and their speed difference between calling function using variable or eval does not differ that much compare to PHP5 VS PHP5call_user_func may also be used to call a closure or anonymous function that has been passed into a user-defined function.

function Benchmark()

{

foreach(func_get_args() as $function)

{

$st = microtime(true);

call_user_func($function);

$et = microtime(true);

echo sprintf("Time: %f", $et - $st) . '
';

}

}

Benchmark(function()

{

for ( $i = 0; $i <= 10000; $i++ )

{ }

},

function()

{

$i = 0;

while ( $i <= 10000 )

{

$i++;

}

});

?>

Returns:

Time: 0.001652

Time: 0.001458>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 = ". $c->name . "\\n\\n";

?>I made a wrapper for call_user_func_array which is really simple and convenient. It takes advantage of the __invoke() magic method :

class Func {

public static function fromFunction($name){

return new Func($name);

}

public static function fromClassMethod($class, $name){

return new Func(array($class, $name));

}

public static function fromObjectMethod($object, $name){

return new Func(array($object, $name));

}

public $function;

public function __construct($function) {

$this->function = $function;

}

public function __invoke(){

return call_user_func_array($this->function, func_get_args());

}

}

?>

Example :

$func = Func::fromObjectMethod($myArrayObject, "offsetGet");

echo $func(3);

?>Actually, as PHP 7.0, when you want to call a static method, you must call:

namespace Foobar;

class Foo {

static public some() {

echo 'Hello World!';

}

}

call_user_func( array( __NAMESPACE__ . '\\Foo', 'some') );

?>

This will output:

Hello World!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():

// RESULTS

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 () { return 1; }

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

?>I was trying to use this function to call a method of an already-instantiated object. I needed to do this with the object itself, not simply call the class' method.

To accomplish this, I really avoided this particular function altogether like this:

if ( method_exists($my_obj, $action) ){

return $my_obj->{$action}();

}

?>

I hope someone else finds this useful. Note that doing this allows you to pass params to the function more-or-less in the same way you would to any other class method.Note that the parser can interpret variables in function syntax, which means you can pass all variables normally (eg: reference).

function myfunction($string, &$int){

echo $string."\n";

$int++;

}

$function_name = "myfunction";

$x = 1336;

$function_name("Hello World", $x);

echo $x;

?>

---

Hello World

1337<?php

class MyClass{

public function hello($str)

{

echo 'hello '. $str;

}

}

$obj = new MyClass();

[$obj, 'hello']('World'); // the array can be called as a functionLets say that $a1 is an object and fn is a function then:

echo $a1->fn('hello world');

echo $a1->{"fn"}('hello world');

echo call_user_func(array($a1, 'fn'),'hello world');

Are three valid ways to do the same.I would just like to say at first that I prefer variable function calls over the use of this function.

However I found that at some times, the use of this function is needed in situtations where variable function calls can not be used. And in those same situations, the use of this function is also better than using eval.

The situation I ran into is this:

I wanted to call object methods dynamically from within the object but with arguments given for possible parameters that the method I will call requires.

The parameters themselves are dynamic, meaning I have no prior knowledge of how many their are, their values, or if they even exist.

Also because object methods are dynamic, meaning I have no prior knowledge which object method will actually be called, I can not simply use variable function calls, call the method and pass any parameters.

So what I simply do is call the object method with an array of parameters, something that, to the best of my knowledge, can not be done with variable function calls, since variable function calls, even though they themeselves are dynamic, passing parameters to them is not.I had a problem where I wanted to parameterize a callback. The end called was in an external class, but I needed to save some state for the callback that didn't make sense to keep in the original object, as it might change from call to call...

class foo

{

function foo()

{

$str = "Hello There";

$str2 = "Carl";

$that =& new holder($str);

call_user_func(array(&$that, 'callback'), $str2);

}

}

class holder

{

function holder($aParam)

{

$this->param = $aParam;

}

function callback($aStr)

{

echo "A=$this->param, B=$aStr\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...

$globalVar = 0;

function &staticFunction()

{

global $globalVar;

return $globalVar;

}

$result =& call_user_func( "staticFunction");

$result = 3;

print "result:". $result . "
\n";

print "globalVar: ". $globalVar . "
\n";

$result2 =& staticFunction();

$result2 = 3;

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.I was trying to call multiple functions within a class, and after a brain frying experience this is what came out... hope it helps:

class Foo {

function hey1($id){echo "In hey1";}

function hey2($id){echo "In hey2";}

#... and so forth ...

function runtest($id) {

#the fun part :)

for($i=1; $i<=2; $i++) {

$fp = "hey".$i;

$this->$fp($id);

}

}

}

?>

It worked like a charm :).<?php

/*

A very simple event handler dispose and change the latest one I did

*/

class Duke

{

//public:

var $m_pRaiser;

var $m_strRaiserFun;

var $m_objArgs;

//public:

function Duke( $pRaiser,

$strRaiserFun,

$objArgs )

{

$this ->m_pRaiser = $pRaiser;

$this ->m_strRaiserFun = $strRaiserFun;

$this ->m_objArgs = $objArgs;

}//end of constructor

}//end of class Duke

class A

{

//protected:

function OnEventHandler( $sender, $args )//virtual

{

$sender ->SayHello();

}//end of OnEventHandler( $sender, $args )

//public:

function OnEvent( $pDuke = null )

{

if( $pDuke == null )

{

call_user_func( array( &$this, "OnEventHandler"), $this, null );

return;

}

call_user_func( array( $pDuke ->m_pRaiser, $pDuke ->m_strRaiserFun ), $pDuke ->m_pRaiser, $pDuke ->m_objArgs );

}//end of OnEvent( $pDuke )

function SayHello()//virtual

{

echo "A::SayHello". "
";

}//end of SayHello()

}//end of class A

class B extends A

{

//public:

function SayHello()//override

{

echo "B::SayHello". "
";

}//end of SayHello()

}//end of class B

//

//Main import to test

//

$a = &new A();

$b = &new B();

$pDuke = &new Duke( $b, "OnEventHandler", null );

$b ->OnEvent();

$b ->OnEvent( $pDuke );

?>Some of the wierder examples below confused me, and made me think that the following would work (but it does!).

class barber{

function shop($one,$two,$three,$four='quartet'){

echo $one.','.$two.','.$three.','.$four;

}

}

$bsq = new barber;

call_user_func(array(&$bsq,'shop'),'one','two','three');

/* Output = one,two,three,quartet */

class bigBarber{

var $quartet;

function bigBarber(){

$this->quartet = 'four';

}

function shop($one,$two,$three,$five='quintet'){

echo $one.','.$two.','.$three.','.$this->quartet.','.$five;

}

}

$bbsq = new bigBarber();

call_user_func(array(&$bbsq,'shop'),'one','two','three');

/* Output = one,two,three,four,quintet */

?>A simple event handler dispose released by useful callback in PHP 4.x

class Duke

{

//public:

var $m_pRaiser;

var $m_strRaiserFun;

var $m_objArgs;

//public:

function Duke( $pRaiser,

$strRaiserFun,

$objArgs )

{

$this ->m_pRaiser = $pRaiser;

$this ->m_strRaiserFun = $strRaiserFun;

$this ->m_objArgs = $objArgs;

}//end of constructor

}//end of class Duke

class A

{

//protected:

function OnEventHandler( $sender, $args )//virtual

{

$sender ->SayHello();

}//end of OnEventHandler( $sender, $args )

//public:

function OnEvent( $pDuke )

{

call_user_func( array( $pDuke ->m_pRaiser, $pDuke ->m_strRaiserFun ), $pDuke ->m_pRaiser, $pDuke ->m_objArgs );

}//end of OnEvent( $pDuke )

function SayHello()//virtual

{

echo "A::SayHello". "
";

}//end of SayHello()

}//end of class A

class B extends A

{

//public:

function SayHello()//override

{

echo "B::SayHello". "
";

}//end of SayHello()

}//end of class B

///

//Main import to test

//

$a = &new A();

$b = &new B();

$pDuke = &new Duke( $b, "SayHello", null );

$b ->OnEvent( $pDuke );

?>Actually, when calling a static method of some class, the params are sent by reference:

class Foo {

private $x = 0;

public function getX(){

return $this->x;

}

public function setX($val){

$this->x = $val;

}

}

class Bar {

static function incStatic(Foo $f){

$f->setX($f->getX()+1);

global $foo;

if($f === $foo) echo ''. __METHOD__ . '() objects are equal
';

else echo ''. __METHOD__ . '() objects are not equal
';

}

public function incNonStatic(Foo $f){

$f->setX($f->getX()+1);

if($f === $foo) echo ''. __METHOD__ . '() objects are equal
';

else echo ''. __METHOD__ . '() objects are not equal
';

}

}

function inc(Foo $f){

$f->setX($f->getX()+1);

if($f === $foo) echo ''. __FUNCTION__ . '() objects are equal
';

else echo ''. __FUNCTION__ . '() objects are not equal
';

}

$foo = new Foo;

$bar = new Bar;

call_user_func('inc', $foo);

call_user_func('Bar::incStatic', $foo);

call_user_func(array($bar, 'incNonStatic'), $foo);

?>

The results on PHP 5.2.6 (macosx 10.5):

inc() objects are not equal

Bar::incStatic() objects are equal

Bar::incNonStatic() objects are not equal

Hope it helps sombody.Based on the previous posts, it appears that using call_user_func can be serveral times slower than using variable substitution. I think these results are somewhat misleading.

I set up a similar test in which a static method of an object was called repeatedly in a loop. I got similar results to those seen; when calling the method using call_user_func the execution was twice that of calling the method directly. However, I then started adding some "meat" to the method in question. In my case, I found that what was constant was not the percentage change, but rather that there is a fixed cost to using call_user_func.

In my case, this fixed cost was 2 microseconds per call. When executing a method that performs no operations, this is a large percentage of the execution time for that method. However, when using this on a method that actually performs some work, the 2 microsecond cost is almost impossible to measure.

It seems to me that if you want to use call_user_func to call a very fast executing method, and you need to do this thousands of times, then you may want to reconsider. However, if you are using this to call methods that are not executed thousands of times, the small fixed cost of using php call_user_func is probably not an issue.It seems like call_user_func() can not be used to create Objects via the new Command.

The Following example dosen't work:

include_once(class_".$type.".php");

$object= new call_user_func ('bdv_'.$type);

?>

But this works:

include_once(class_".$type.".php");

$constr = 'bdv_'.$type;

$object = new $constr();

?>With overload()ed classes call_user_func_* calls real class methods only. If the method does not exist then PHP does not try with the "__call()" magic method (at least until PHP 4.3.3). See this:

class A

{

function A() {}

function __call($method, $args, &$ret) {

echo "__call(): You called '{$method}()'
\n";

return true;

}

function regular() {

echo "You called 'regular()'
\n";

}

};

overload("A");

$a = new A;

$a->regular(); // Works, calls regular()

call_user_func(array(&$a, "regular")); // Works, calls regular()

$a->hello(); // Works, calls __call()

call_user_func(array(&$a, "hello")); // Does NOT work!

?><?php call_user_func()?> and <?php call_user_func_array()?> hide some errors (notices, warnings and maybe errors), even if is display_errors turned on and error_Reporting is set to E_ALL|E_STRICTWe can achieve the same dynamically without call_user_func like this

class myclass {

public function say_hello()

{

echo "Hello!\n";

}

}

$classname = "myclass";

$myobject = new myclass();

$var = "say_hello";

(new myclass)->{$var}();

call_user_func(array(new myclass(), $var));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值