Function handling 函数
在线手册:中文 英文
PHP手册

call_user_func

(PHP 4, PHP 5)

call_user_funcCall the callback given by the first parameter

说明

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

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

参数

callback

The callable to be called.

parameter

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

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

返回值

Returns the return value of the callback, or FALSE on error.

更新日志

版本 说明
5.3.0 The interpretation of object oriented keywords like parent and self has changed. Previously, calling them using the double colon syntax would emit an E_STRICT warning because they were interpreted as static.

范例

Example #2 call_user_func() example

<?php
function barber($type)
{
    echo 
"You wanted a $type haircut, 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 #3 call_user_func() using namespace name

<?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!

Example #4 Using a class method with 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!

Example #5 Using lambda function with 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()),如在前一个回调中有未捕获的异常,其后的将不再被调用。

参见


Function handling 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: Call the callback given by the first parameter

用户评论:

bkfake-php at yahoo dot com (15-Mar-2012 01:53)

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

documentation should say "before PHP 5.4"

documentation should also mention that PHP 5.3.x call-time pass by reference thows a warning...BUT
call_user_func_array('function', array(&$a));    does not throw a warning

paul dot e dot s dot wormer at gmail dot com (10-Feb-2012 10:58)

Example#1 (with Xamp, PHP v. 5.3.8, Windows 7) writes

Warning: Parameter 1 to increment() expected to be a reference, value given in C:\xampp\htdocs\call_user_func.php on line 9
0
1

--------
When argument of increment is by-value (remove & from &$var), warning is gone and output is
0
1

dexen dot devries at gmail dot com (04-Nov-2011 01:00)

In PHP v5.2, you /can/ use call_user_func(array($this, 'parent::SOME_FUNCTION')).

If you don't have custom __autoload() function, you are good to go.

If you do have custom __autoload(), you need to make it `parent' aware. Something like:

<?php
function __autoload($classname) {
  if (
$classname === 'parent')
    return;
  else
   
//((load class definition))
}
?>

Rationale: PHP 5.2 surprisingly tries to autoload a class named `parent'. However, if you don't do anything in __autoload() for the `parent' class, it'll work just fine.

Gavin (23-Sep-2011 10:48)

If using call_user_func() to pass resources (e.g. pipes created by proc_open), pass them using an array or object containing the resources, instead of "naked".

Bad: call_user_func($callback, $pipes[0], $pipes[1], $pipe[2]);

Good: Bad: call_user_func($callback, $pipes);

Passing the variables containing resource ids in the "bad" example above appears to work, but can cause troubles later when trying to close STDIN ($pipe[0] for example), and then read the output of the spawned child from $pipes[1].  The child process may or may not hang in read(), as reported by strace, even though the passed resources look valid, and the fclose on the stdin resource returns true.

Switching to the "good" example above solved the issue above for me.

Peace to you.

blakerenton09 at yahoo dot com (06-Jun-2011 12:45)

call_user_func may also be used to call a closure or anonymous function that has been passed into a user-defined function.

<?php
function Benchmark()
{
    foreach(
func_get_args() as $function)
    {       
       
$st = microtime(true);
       
call_user_func($function);
       
$et = microtime(true);
        echo
sprintf("Time: %f", $et - $st) . '<br />';
    }
}

Benchmark(function()
{
    for (
$i = 0; $i <= 10000; $i++ )
    { }
},
function()
{
   
$i = 0;
    while (
$i <= 10000 )
    {
       
$i++;
    }
});
?>

Returns:
Time: 0.001652
Time: 0.001458

romainbessuges at gmail dot com (09-May-2011 01:50)

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

<?php
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 :

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

echo
$func(3);
?>

gskluzacek dot nospam at gmail dot com (11-Sep-2010 06:38)

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:

<?php

$method_name
= "AMethodName";

$obj = new ClassName();

$obj->{$method_name}();

?>

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

Regards,
-- Greg

moisadoru at gmail dot com (13-May-2010 04:49)

Actually, when calling a static method of some class, the params are sent by reference:
<?php
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 '<span style="color: blue">' . __METHOD__ . '() objects are equal</span><br />';
        else  echo
'<span style="color: red">' . __METHOD__ . '() objects are not equal</span><br />';
    }
    public function
incNonStatic(Foo $f){
       
$f->setX($f->getX()+1);
        if(
$f === $foo) echo '<span style="color: blue">' . __METHOD__ . '() objects are equal</span><br />';
        else  echo
'<span style="color: red">' . __METHOD__ . '() objects are not equal</span><br />';
    }
}

function
inc(Foo $f){
   
$f->setX($f->getX()+1);
    if(
$f === $foo) echo '<span style="color: blue">' . __FUNCTION__ . '() objects are equal</span><br />';
    else  echo
'<span style="color: red">' . __FUNCTION__ . '() objects are not equal</span><br />';
}

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

Nitrogen (05-Oct-2009 12:08)

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.

<?php
// 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.

edgar dot klerks at gmail dot com (17-Mar-2009 03:18)

An entirely OO solution to add dynamicly methods to classes, I used in a project:
<?php
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:

<?php

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:

<?php
$bla
= new ProductPart(array('HelloWorld' => 'Hello world'));
$hello = new helloPlugin();
$bla->register($hello);
$bla->HelloWorld();
$bla->unregister($hello);
$bla->HelloWorld();

?>

dead,screamer@seznam,cz (21-Dec-2008 04:50)

<?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_STRICT

Maxdamantus (04-Nov-2007 06:26)

Note that the parser can interpret variables in function syntax, which means you can pass all variables normally (eg: reference).

<?php
function myfunction($string, &$int){
    echo
$string."\n";
   
$int++;
}
$function_name = "myfunction";
$x = 1336;
$function_name("Hello World", $x);
echo
$x;
?>
---
Hello World
1337

chris at NOSPAM dot panospheric dot com (23-Sep-2007 03:37)

I am looking for a way to make dynamic method calls on objects. I may have overlooked other posts but here is the example anyway.

<?php
 
class MyClass1 {

   var
$input1 = 4;
   var
$input2 = 5;

   function
MyClass1(){}

   function
adding() {

  
$var1 = $this->input1;
  
$var2 = $this->input2;
    
  
$result = $var1 + $var2;

   return
$result;
   }

}

class
MyClass2 {

   var
$anotherObject;

   function
MyClass2($anotherObject){
     
    
$this->anotherObject = &$anotherObject;

   }

}

?>

Now we will call a method of object of object:

<?php

$myclass1Object
=& New MyClass1();

$myclass2Object =& New MyClass2(&$myclass1Object);

$output $myclass2Object->anotherObject->adding();

echo
$output; //outputs 9 if all is well

?>

Now we want to do it dynamically that works in PHP 4 and 5. There are two ways of doing this.

First Method using variable variables:

<?php

$objectName
= 'myclass2Object'//case sensitive.
$anotherObject = 'anotherObject';//case sensitive
$functionName = 'adding';

$output = $$objectName->{$anotherObject}->{$functionName}();    

echo
$output; //will output 9 as well

?>

Now the same using call_user_func():

<?php

$output
= call_user_func(array(&$$objectName->{$anotherObject},$functionName));

echo
$output; //outputs 9 as well

?>

If you have a method of an object of an object that requires parameters you can do this:

<?php

call_user_func
(array(&$objectName->{$anotherObject},$functionName), $arg1, $arg2);

?>

I hope this might be helpful to someone.

Cheers.

Knightnet (07-Sep-2007 01:31)

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.

serge belychev (23-Aug-2007 03:08)

For calling a class method from version 5.2.3 you can write

<?php
class myclass {
    static function
say_hello()
    {
        echo
"Hello!\n";
    }
}

$classname = "myclass";

call_user_func('myclass::say_hello');
?>

lsblsb at gmx dot de (29-Jun-2007 12:55)

referring to Mr.KTO (and Bug #24931):
[system: PHP 5.2.0-8] - _doesnt_ pass by reference, at least when using the old syntax with the '&'.

when you pass your object by reference using call_user_func, any changes made on that object within the called function wont effect your "original" object.

you should use mixed call_user_func_array ( callback $function, array $param_arr ) instead or eval() (slower).

Mr.KTO (14-Jun-2007 03:39)

To send an object to your function by link, using call_user_func it's not enough (in php4) to define func(&$obj) { ... }

You need: call_user_func("callback", &$myobj)

(in php5 objects are sending by link as default)

jaimz at vertigolabs dot org (27-Oct-2006 06:40)

replay to bkfake-php at yahoo dot com's comment:

that's not passing by referance, your explicitly setting the value of $testy's member variable, infact, if you take the & out of your outsidefunc() it still works...

bkfake-php at yahoo dot com (26-Oct-2006 06:18)

I have found a case where the parameters ARE passed by reference

class test
{
    function test()
    {
        $this->passme = '';
        call_user_func('outsidefunc',$this);
        // $this->passme is now 'not empty'
        // with 5.1.2
        // not so with php 4.3.10...
    }
}

function outsidefunc(&$testy)
{
     $testy->passme = 'not empty';
}
$test = new test();
echo 'passme = '.$test->passme;

Typer85 at gmail dot com (12-Sep-2006 11:57)

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.

watchout at no dot spam dot please (29-Aug-2006 02:05)

> This particular case will not work. The user functions can only be successfully called (as the documentation alludes to), with static calls to class functions.

actually it *does* work on PHP 5.0.2 (tested), and should also work on PHP 4.3.x (untested). Also the documentation does not state that only calls to static class methods are possible, but it says clearly that calls to OBJECT (thats dynamic) methods are possible: http://cz.php.net/manual/en/language.pseudo-types.php (see under type callback)

rlansky at webroot dot com (15-Jul-2006 12:17)

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.

Maresa (13-Apr-2006 11:41)

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 PHP5

insta at citiesunlimited dot com (06-Feb-2006 08:15)

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:

<?php

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

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

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

?>

Marco (05-Oct-2005 09:42)

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

<?php
 
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";

?>

php at REMOVEMEkennel17 dot co dot uk (09-Aug-2005 04:46)

re comment by mw at lanfear dot com

I am using PHP 4.3.2 and that technique works fine here as well.

mw at lanfear dot com (26-Jul-2005 09:49)

This function is actually quite useful for calling static methods on classes, which you CANNOT call as:

$v1 = 'MyClass';
$m1 = 'method';
$v1::$m1();           // syntax error -- not permitted.

The following, however, DOES work quite well, and is hopefully slightly faster than eval() ...

$ar = array($v1, $m1);

call_user_func($ar);    // works teh awes0me!!1!

[I am, however, presuming PHP5 here ...]

info at webseiteselberpflegen dot de (18-May-2005 09:00)

It seems like call_user_func() can not be used to create Objects via the new Command.

The Following example dosen't work:

<?php
 
include_once(class_".$type.".php");
 
$object = new call_user_func ('bdv_'.$type);
?>

But this works:

<?php
    include_once(class_"
.$type.".php");
   
$constr = 'bdv_'.$type;
   
$object = new $constr();
?>

d at safetypub dot org (15-Mar-2005 04:43)

callbacks, this par excellence, goes with set error handler, everywhere you'ren't sure of extensio de intensionibus (animis alii).

<?php

$checkMe
= null;
$detail = array();
set_error_handler("imErrant");

array_shift($argv);
if (
$argc == 1){
       
call_user_func(strtolower($argv[0]));
} else if(
$argc == 2){
       
call_user_func(strtolower($argv[0]), $argv[1]);
}
else
       
call_user_func_array(strtolower($argv[0]),array_shift($argv));

if(
$checkMe)var_export($detail);

function
imErrant($no, $str, $file, $line)
{
    global
$checkMe, $detail;
   
$checkMe = $no;
   
$detail = array($str, $file, $line);
}
?>

(25-Feb-2005 03:46)

<?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" . "<br>";
    }
//end of SayHello()

}//end of class A

class B extends A
{
//public:
   
function SayHello()//override
   
{
        echo
"B::SayHello" . "<br>";
    }
//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 );
?>

zxy at estec-jp dot com (24-Feb-2005 10:57)

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

<?php
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" . "<br>";
    }
//end of SayHello()

}//end of class A

class B extends A
{
//public:
   
function SayHello()//override
   
{
        echo
"B::SayHello" . "<br>";
    }
//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 );
?>

bostjan dot skufca at domenca dot com (15-Dec-2004 08:33)

This is the CORRECTED VERSION of previous note. After playing a while I realised that objects are not passed by reference implicitly, you have to do it on your own, so:

call_user_func(array($objectBar, 'methodFoo')); // case sensitive

first duplicates object $objectBar (internally) and only then calls it's methodFoo. This kind of use is discouraged as it may result in "unpredicted behaviour".

Correct version is here.
call_user_func(array(&$objectBar, 'methodFoo')); // case sensitive
(note the reference operator).

--- and the corrected note is here ---

I couldn't find any simple list of available callback variations, so I made one. It is tested on PHP 4.3.9 only.

If you need to call ordinary function:
call_user_func('funcFoo');

If you need to call CLASS method (NOT object):
call_user_func(array('classBar', 'methodFoo')); // case insensitive

If you need to call OBJECT method:
call_user_func(array(&$objectBar, 'methodFoo')); // case sensitive

If you need to call method of object of object:
call_user_func(array(&$objectBar->objectTor, 'methodFoo')); // case sensitive

If you need to call object method from within the very same object (NOT CLASS!):
call_user_func(array(&$this, 'methodFoo'));

(07-Oct-2004 08:23)

If you are trying to instantiate an object from a class whose name is dynamic, you WILL NOT be able to do this with call_user_func() and I do not suggest that you do it with eval(). The way to do it is actually much simpler than i thought. As far as i know this works in PHP 4 and 5:

<?PHP
class foo {
 var
$boo;
    function
foo( $someVal ) {
    
$this->boo = $someVal;
    }
}

$ClassToUse = "foo";
$bar = new $ClassToUse('test');
echo
$bar->boo;
?>

arjini at mac dot com (30-Mar-2004 01:04)

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

<?php

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 */

?>

Kris Koskelin (22-Jan-2004 11:21)

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:

<?php
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.

Michele.Manzato at verona.miz.it (29-Sep-2003 04:49)

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:

<?php
class A
{
    function
A() {}
   
    function
__call($method, $args, &$ret) {
        echo
"__call(): You called '{$method}()'<br>\n";
        return
true;
    }
   
    function
regular() {
        echo
"You called 'regular()'<br>\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!
?>

Carl (28-Jul-2003 07:53)

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...

<?php
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";
    }
}
?>

matt at tasonline dot com (23-Nov-2002 08:24)

On PHP 4.2.3 (not sure about older releases) you can send objects by reference by sending the reference from call_user_func()

<?php
function myFunction(@$obj)
{
  
$obj->doThis('hello');
   return
0;
}

$myObj = new CObject();

call_user_func('myFunction', @$myObj);
?>

phil at gettcomm dot com (22-May-2002 03:51)

if you need to get a reference back from a method, you can work around call_user_func()'s shortcomings like this:

<?php

$globalObj
;

class
tClass
{
    function &
instance()
    {
        global
$globalObj;
        if(!
is_object($globalObj))
        {
           
$globalObj = new tClass();
        }
        return
$globalObj;
    }
}

$classname = "tClass";
# calling the function this way won't
# return a reference.
$test = &call_user_func(array($classname,"instance"));
# but if we call it again with the instance
# that we just got, it'll be the right
# one
$test = &$test->instance();
# so test is now a reference to $globalObj, just like it should be

# let's verify it:
$test->blah=1;

echo
"<pre>";
print_r($test)."\n";
print_r($globalObj);
echo
"</pre>";
# there, now it behaves just like you'd expect

?>

teleware at mind dot net (08-Apr-2002 09:34)

I ran into some quirky behavior using call_user_func with an object.  The function parseAction() below lets me call any of my object's methods by passing the name of the method into a page (e.g. http://xyz.com/page.php?action=login).

<?php
class MyClass {

    function
parseAction($actionKey)
    {
        global
$METarget;

        if(
method_exists($this,$actionKey))
        {
           
call_user_func(array(&$this,$actionKey));
            return;
        }
        else
        {
            exit(
"Unknown action keyword: $actionKey");
        }
    }

    ...
   
// other methods
   
...
}
?>

I found that my member variables weren't always being updated correctly.  The numberic values were preserved but the string variables retained their old value.  The solution was to put the reference operator '&' in front of the object's variable.  In this case it's $this because I'm calling it from within the object but this was also true when calling parseAction from an instanciated object e.g. call_user_func(array(&$myObject,$actionKey))

dougqh at hotmail dot com (08-Mar-2002 01:16)

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...

<?php
$globalVar
= 0;

function &
staticFunction()
{
   global
$globalVar;
  
   return
$globalVar;
}

$result =& call_user_func( "staticFunction" );

$result = 3;

print
"result:" . $result . "<br/>\n";
print
"globalVar: " . $globalVar . "<br/>\n";

$result2 =& staticFunction();

$result2 = 3;

print
"result2: " . $result2 . "<br/>\n";
print
"globalVar: " . $globalVar . "<br/>\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.

danyloco at yahoo dot com (18-Jul-2001 12:31)

I was trying to call multiple functions within a class, and after a brain frying experience this is what came out... hope it helps:

<?php
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 :).

andreyhristov at yahoo dot com (22-Aug-2000 02:09)

Let say we construct somehow the name of the function. In some cases we can use nested  'switch'  but the alternative is to to use for and parse a string to construct  the  function  name, after than  we also can construct and the parameter(s) for it. It  is like using of eval. I use it in  one of my projects to construct a name of nested array like $ar['1999'['july']['29']['19'], etc.

the problem is in that I'm parsing a string to construct the name. If I've {1:2:3}  the array name  will be $ar['1']['2']['3'] but if i've
{1:2:3:4:5} it will  be $ar['1']['2']['3']['4']['5'].

Eval is the only way (very hard because of characters escaping is needed)  to do it. So this function is of the type of EVAL().
USE IT wherever your script is  'self-modified';