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

call_user_func_array

(PHP 4 >= 4.0.4, PHP 5)

call_user_func_arrayCall a callback with an array of parameters

说明

mixed call_user_func_array ( callable $callback , array $param_arr )

Calls the callback given by the first parameter with the parameters in param_arr.

参数

callback

The callable to be called.

param_arr

The parameters to be passed to the callback, as an indexed array.

返回值

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 #1 call_user_func_array() example

<?php
function foobar($arg$arg2) {
    echo 
__FUNCTION__" got $arg and $arg2\n";
}
class 
foo {
    function 
bar($arg$arg2) {
        echo 
__METHOD__" got $arg and $arg2\n";
    }
}


// Call the foobar() function with 2 arguments
call_user_func_array("foobar", array("one""two"));

// Call the $foo->bar() method with 2 arguments
$foo = new foo;
call_user_func_array(array($foo"bar"), array("three""four"));
?>

以上例程的输出类似于:

foobar got one and two
foo::bar got three and four

Example #2 call_user_func_array() using namespace name

<?php

namespace Foobar;

class 
Foo {
    static public function 
test($name) {
        print 
"Hello {$name}!\n";
    }
}

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

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

?>

以上例程的输出类似于:

Hello Hannes!
Hello Philip!

Example #3 Using lambda function

<?php

$func 
= function($arg1$arg2) {
    return 
$arg1 $arg2;
};

var_dump(call_user_func_array($func, array(24))); /* As of PHP 5.3.0 */

?>

以上例程会输出:

int(8)

注释

Note:

Before PHP 5.4, referenced variables in param_arr are passed to the function by reference, regardless of whether the function expects the respective parameter to be passed by reference. This form of call-time pass by reference does not emit a deprecation notice, but it is nonetheless deprecated, and has been removed in PHP 5.4. Furthermore, this does not apply to internal functions, for which the function signature is honored. Passing by value when the function expects a parameter by reference results in a warning and having call_user_func() return FALSE (there is, however, an exception for passed values with reference count = 1, such as in literals, as these can be turned into references without ill effects — but also without writes to that value having any effect —; do not rely in this behavior, though, as the reference count is an implementation detail and the soundness of this behavior is questionable).

Note:

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

参见


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

用户评论:

jaxxed (2012-07-10 04:42:09)

For anyone looking for the means to test for the first parameter before passing to this function, look at the is_callable (http://php.net/manual/en/function.is-callable.php) variable handler.

<?php

$handler 
= array( 'MyClass''MyMethod');
$params = array(1,2,3,4);

if ( 
is_callable($handler) ) { call_user_func_array$handler $params ); }

?>

tracid2008 AT googlemail.com (2011-03-22 02:42:01)

I think a better solution is to use ReflectionClass instead of call_user_func_array:

<?php
$rc 
= new ReflectionClass('SomeClass');
$class $rc->newInstanceArgs(array('foo''bar'));
 
echo 
$class->doSomething();
?>

gaojingjing2008 at gmail dot com (2011-01-14 01:28:38)

in PHP 5.2.* when pass string to $param_arr, there will not be warning, but in PHP 5.3, there was a warning

Brad Proctor (2010-11-06 21:07:40)

This function is relatively slow (as of PHP 5.3.3) and if you are calling a method with a known number of parameters it is much faster to call it this way:

$class->{$method}($param1, $param2);

vs

call_user_func_array (array($class, $method), array($param1, $param2));

But if you don't know how many parameters...

The wrapper function below is slightly faster, but the problem now is that you are making two function calls.  One to the wrapper and one to the function.

However, If you are able to take this code out of the function and use it inline it is nearly twice as fast (in most cases) as calling call_user_func_array natively.

<?php
function wrap_call_user_func_array($c$a$p) {
    switch(
count($p)) {
        case 
0$c->{$a}(); break;
        case 
1$c->{$a}($p[0]); break;
        case 
2$c->{$a}($p[0], $p[1]); break;
        case 
3$c->{$a}($p[0], $p[1], $p[2]); break;
        case 
4$c->{$a}($p[0], $p[1], $p[2], $p[3]); break;
        case 
5$c->{$a}($p[0], $p[1], $p[2], $p[3], $p[4]); break;
        default: 
call_user_func_array(array($c$a), $p);  break;
    }
}
?>

orestes at orestescarracedo dot com (2010-11-05 13:24:04)

It's not commented above:

This function behaves as call_user_func. To call a method of a class instace, instead of passing the function name as the first argument, pass an array like ($classInstance, 'methodName')

<?php
public class Person {
    private 
$name null;
    private 
$pocketContentsnull;

    protected function 
__construct() {
        
$this->name 'My creator was too lazy to name me';
    }
    public function 
getName() {
        return 
$this->name;
    }
    public function 
setName($name) {
        
$this->name $name;
    }
    public function 
getPocketContents() {
        return 
$this->$pocketContents;
    }
    public function 
setPocketContents() {
        
$args func_get_args();
        
$this->$pocketContents $args;
    }
}

$contents = array();
$contents[0] = 'random';
$contents['foo'] = 'bar';

$subobject = array();
$subobject['param'] = 'value';
$contents['subobject'] = $subobject;

call_user_func(($myInstance'setPocketContents'), $contents);
?>

hinom06 [at] hotmail.co.jp (2010-09-14 21:27:01)

<?php

/*
Usage sample to apply any filter in a string.
*/

class Strings
{
    function 
Foo$v$allow '' )
    {
        return 
strip_tags$v$allow );
    }

    
// add an element at the beginning of an array
    // thanks for Vidal Rodríguez
    // http://www.php.net/manual/en/function.array-push.php#98299
    
function ArrayRpush$arr$item )
    {
      return 
array_pad$arr, -( count$arr ) + ), $item );
    }

}

Class 
Functions
{

    function 
Call$f )
    {
        return 
call_user_func_array$f[0], $f[1] );
        
        
/* usage sample:
            // 
            // calling function
            Functions::Call( 'strip_tags', array( '<br>foo<br>bar</b>', '<br><b>' ) );
            
            // calling object
            Functions::Call( array( 'Strings', 'StripTags' ), array( '<br>foo<br>bar</b>', '<br><b>' ) );
        */
    
}

}

$form = array(
            
'field' => array(
                            
'value'         => '<b>foo bar</b><br><script>alert("1");</script>',
                            
'pre-filter'    => array( array( 'Strings''Foo' ) , array( '<b><br>' ) ),
                            ),
            );

$v    $form['field'];
$f    $v['pre-filter'];
$f[1] = isset( $v['pre-filter'][1] ) ? Strings::ArrayRpush$f[1], $v['value'] ) : $f[1] = array( $v['value'] );

echo 
Functions::Call$f );

?>

Kris dot Craig at gmail dot com (2010-06-16 15:28:58)

Many people have wondered how to effectively implement dispatch tables in PHP.  Here's my answer to that (if you'll forgive my creative flair):

<?php

/*
 * Using dispatch tables in PHP.
 * 
 * --Kris Craig
 */

define"YOUR_MOTHER",  );
define"YOUR_FATHER",  );
define"YOUR_BROTHER");
define"YOUR_SISTER",  );

class 
MyFamily
{
    static 
$dispatch = array( YOUR_MOTHER => "Mom"YOUR_FATHER => "GetPrisonInmate"YOUR_BROTHER => "ReplaceName"YOUR_SISTER => "LazyGirl" );
    static 
$args = array( YOUR_MOTHER => array(), YOUR_FATHER => array( "55170-054"TRUE ), YOUR_BROTHER => array(), YOUR_SISTER => array() );
    
    function 
GetDispatch$fromwhere )
    {
        return 
call_user_func_array( array( selfself::$dispatch[$fromwhere] ), self::$args[$fromwhere] );
    }
    
    function 
Mom()
    {
        return 
"Mommy loves you!";
    }
    
    function 
GetPrisonInmate$PrisonerID$GoodBehavior )
    {
        
//Check prison records for his ID, then....
        
        
if ( $GoodBehavior )
        {
            
$parole "APPROVED";
        }
        else
        {
            
$parole "DENIED";
        }
        
        return 
"Your father (#$PrisonerID) has $remaining years left in his sentence.  His most recent parole application has been:  $parole";
    }
    
    function 
ReplaceName()
    {
        return 
"Her name is Sally now.";
    }
    
    function 
LazyGirl()
    {
        print 
"Your sister needs to get out more....";
        
        
//sleep( pow( 60, 2 ) * 18 );  //You can sleep later!
        
        
die( "Nah, I'm too tired." );
    }
}

print 
"Status on family member: " MyFamily::GetDispatchYOUR_FATHER );

?>

noone at example dot com (2010-04-21 15:03:19)

For those of you that have to consider performance: it takes about 3 times as long to call the function this way than via a straight statement, so whenever it is feasible to avoid this method it's a wise idea to do so.
Note that eval() is about 10 times slower than a straight statement to call a function with arguments, so this is definitely a better option than using eval() even if you only consider performance.

Guy Paddock (2010-04-15 14:14:58)

It appears that it is safe to pass an associative array in for $param_arr. The parameters will still be passed in the order the elements appear in the array, not alphabetical key order.

kweejee at gmail dot com (2010-01-22 20:04:32)

I recently had
<?php
  call_user_func_array
('MyClass::myFunction', array(010));
?>
working on my home server, but when I uploaded it to a host with a different version of PHP it stopped working and gave the error message "call_user_func_array() [function.call-user-func-array]: Unable to call MyClass::myFunction()" The solution I found was to use this instead:
<?php
  call_user_func_array
(array('MyClass''myFunction'), array(010));
?>

aj at ajbrown dot org (2009-12-22 19:30:29)

Just a heads up, the second parameter MUST be an array if it's specified, but that doesn't seem to be enforced until ~5.3.
I just pulled my hair out with an old installation of CakePHP because it was passing NULL instead of an empty array.

mrextreme at freemail dot hu (2009-12-07 08:34:39)

If you are using PHP < 5.3 and want to call the parent class' __construct() with a variable parameter list, use this:

<?php
public function __construct()
{
    
$vArgs func_get_args(); // you can't just put func_get_args() into a function as a parameter
    
call_user_func_array(array('parent''__construct'), $vArgs);
}
?>

dmitry dot revenko at businessmedia dot ru (2009-09-25 05:28:10)

Just hope this note helps someone (I killed the whole day on issue).

If you use something like this in PHP < 5.3:
<?php call_user_func_array(array($this'parent::func'), $args); ?>
Such a script will cause segmentation fault in your webserver.

In 5.3 you should write it:
<?php call_user_func_array('parent::func'$args); ?>

al dot james at NOSPAMGMAIL dot com (2009-06-17 03:19:45)

If you want to use call_user_func_array to call an objects constructor, this works for me:

<?php
$obj 
= new $object_class();
call_user_func_array(array($obj'__construct'), $args);
?>

(However it does depend on having a constructor where all arguments are optional, which may or may not be possible)

So this is a two part initiation, the object gets initiated with no arguments first (hence requiring options constructor params), and then __construct gets called again. Thus, you should not do anything in your constructor that triggers effects outside the class... it should just set the objects state.

Damin (2009-06-13 00:06:53)

Those having the passing by reference issue can use this simple hack.
I?m really not sure WHY this works, but it does, and it does not make use of EVAL or other questionable functions.
<?php
    
function executeHook($name$type='hooks'){
        
$args func_get_args();
        
array_shift($args);
        
array_shift($args);
        
//Rather stupid Hack for the call_user_func_array();
        
$Args = array();
        foreach(
$args as $k => &$arg){
            
$Args[$k] = &$arg;
        }
        
//End Hack
        
$hooks = &$this->$type;
        if(!isset(
$hooks[$name])) return false;
        
$hook $hooks[$name];
        
call_user_func_array($hook$Args);
    }
?>

All it?s doing is copying the args ($args) into a new array ($Args) by reference, which i would think would be identical to the original array in every way (that matters).

Note the code here is an example of usage. The actual hack is denoted by comments.
If someone knows a better alternative, by all means, i would love to see it.

Freek (at) Gruntjes.net (2009-04-07 01:53:58)

I just noticed that when you use this function with parameters that need to be passed by reference it will not work.

<?php
function refFunc(&$var)
{
  
$var .= 'bar';
}

$var 'foo';
?>

call_user_func_array('refFunc', array($var));
echo $var;

will output 'foo' and not  'foobar'. Witch is logical since you are declaring a new variable with array($var) however not so obvious.

thiago dot henrique dot mata at gmail dot com (2008-07-22 14:17:16)

<?php
Class Delegate
{
    private 
$arrInstances = array();
    
    protected function 
addObject$oElement )
    {
        
// add one element on the end of the stack  //
        
$this->arrInstances[] = $oElement;
    }    
    
    public function 
__call$strMethod$arrParams )
    {
        
// for each element in instance //
        
foreach( $this->arrInstances as $oElement )
        {
            
// get the class of the element //
            
$strClass get_class$oElement );
            
// get all methods of the class  //
            
$arrMethods get_class_methods$strClass );
            
// case the method exists into this class  //
            
if( in_array$strMethod $arrMethods ) ) 
            {
                
// prepare caller //
                
$arrCaller = Array( $strClass $strMethod );
                
// return the result of the method into the object  //
                
return call_user_func_array$arrCaller$arrParams );
            }
        }
        
// any object has the method //
        // throw a exception //
        
throw new Exception" Method " $strMethod " not exist in this class " get_class$this ) . "." );
    }
}

class 
Log
{
    public function 
sayHi()
    {
        print 
"hi!" "<br/>\n";
    }
    
    public function 
sayMyName()
    {
        print 
"log" "<br/>\n";
    }
}

class 
Other
{
    public function 
sayHello()
    {
        print 
"hello there!" "<br/>\n";
    }
    
    public function 
sayMyName()
    {
        print 
"other" "<br/>\n";
    }
}

class 
Example extends Delegate
{
    public function 
__construct()
    {
        
$this->addObject( new Log() );
        
$this->addObject( new Other() );
    }
}

$oExample = new Example();
$oExample->sayHi();
$oExample->sayHello();
$oExample->sayMyName();

/* 
    hi!<br/>
    hello there!<br/>
    log<br/>
*/
?>

dnhuff at acm.org (2008-06-07 11:57:16)

It appears that when PHP executes something like:
$a = array(1,2,3);
$b =& $a[1];
both $b and $a[1] are converted into references to a common value -- makes sense until you transfer that to a call_user_func:
call_user_func_array('foo', $a);
suddenly, inside foo, the second parameter is passed by reference!
And you can't call this wrong, only another subtly of references.
Note it appears that ksort($a) will remove the reference as well as put the elements in key order so you (probably) get what you expect. (see below on the use of a foreach ($a as &v).)

dnhuff at acm.org (2008-06-07 11:38:38)

the order of argument correspondence from the array to the function formal parameters is by 'natural order' of the array and not explicit numerical key order.
So: $a[0] = 'arg 1'; $a[2] = 'arg 2'; $a[1] = 'arg 3';
call_user_func_array('foo', $a);
delivers the args to foo in the order the keys were inserted! as in...
foo($a[0], $a[2], $a[1]);
if you wanted something else, ksort the array first.

aeolianmeson at 8n54tvv dot blitzeclipse dot com (2008-05-27 08:48:52)

There's a possibility that call_user_func_array(), call_user_func(), and Exception::getTrace() will cause a trace entry to not have the 'file' or 'line' elements.
Dustin Oprea

richard_harrison at rjharrison dot org (2007-04-11 02:31:23)

If you are thinking of using call_user_func_array to instantiate an object (see comments below using Reflection) then since v5.1.3 you can use the Reflection::newInstanceArgs() method.

<?php

// arguments you wish to pass to constructor of new object
$args = array('a''b');

// class name of new object
$className 'myCommand';

// make a reflection object
$reflectionObj = new ReflectionClass($className);

// use Reflection to create a new instance, using the $args
$command $reflectionObj->newInstanceArgs($args);

// this is the same as: new myCommand('a', 'b');
?>

levi at alliancesoftware dot com dot au (2007-02-08 14:50:29)

Regarding the comments below about calling parent constructors:

PHP5 with E_STRICT no longer allows calls as below:

<?php
// Causes an error with E_STRICT
call_user_func_array(array('parent''__construct'), $args);
?>

It gives an error because you are trying to call a nonstatic function as if it was static. The correct syntax is

<?php
// Works fine
call_user_func_array(array($this'parent::__construct'), $args);
?>

(2006-05-15 02:43:06)

For those wishing to implement call-by-name functionality in PHP, such as implemented e.g. in DB apis, here's a quick-n-dirty version for PHP 5 and up
<?php
/**
 * Call a user function using named instead of positional parameters.
 * If some of the named parameters are not present in the original function, they
 * will be silently discarded.
 * Does no special processing for call-by-ref functions...
 * @param string $function name of function to be called
 * @param array $params array containing parameters to be passed to the function using their name (ie array key)
 */
function call_user_func_named($function$params)
{
    
// make sure we do not throw exception if function not found: raise error instead...
    // (oh boy, we do like php 4 better than 5, don't we...)
    
if (!function_exists($function))
    {
        
trigger_error('call to unexisting function '.$functionE_USER_ERROR);
        return 
NULL;
    }
    
$reflect = new ReflectionFunction($function);
    
$real_params = array();
    foreach (
$reflect->getParameters() as $i => $param)
    {
        
$pname $param->getName();
        if (
$param->isPassedByReference())
        {
            
/// @todo shall we raise some warning?
        
}
        if (
array_key_exists($pname$params))
        {
            
$real_params[] = $params[$pname];
        }
        else if (
$param->isDefaultValueAvailable()) {
            
$real_params[] = $param->getDefaultValue();
        }
        else
        {
            
// missing required parameter: mark an error and exit
            //return new Exception('call to '.$function.' missing parameter nr. '.$i+1);
            
trigger_error(sprintf('call to %s missing parameter nr. %d'$function$i+1), E_USER_ERROR);
            return 
NULL;
        }
    }
    return 
call_user_func_array($function$real_params);
}
?>

eugene at artprime dot ru (2005-12-23 02:59:19)

<?php
  
return call_user_func_array(
    array(new 
ReflectionClass($className), 'newInstance'),
    
$functionParameters
  
);
?>

Look here: http://www.zend.com/zend/week/week182.php#Heading1

crocodile2u at yandex dot ru (2005-12-20 05:06:43)

Here is another version of createObjArray() function written here earlier by taylor.

Believing that using 'eval()' is at least "dirty", I came to the following solution (with a help of panchous - at phpclub dot ru forums ). This solution utilizes the new Reflection API.

<?php
function & createObjArray($type$args = array()) {
    
$reflection = new ReflectionClass($type);
    
$output     call_user_func_array(array(&$reflection'newInstance'), $args);
    return 
$output;
}
?>

Egor (2005-11-15 21:35:54)

Note that, despite the name, this does work on builtin functions (and object methods with the array(&$obj, $method) syntax), not just user-defined functions and methods.

rrant (at) gmail (dot) com (2005-11-10 03:50:37)

Just an extra for the post of amer at o2 dot pl:

If you need to call the PARENT method:
call_user_func_array(array('parent', 'method'), $args);

With that, if you need to call a constructor and/or add some extra code to the instantiation process:

<?php
function __construct() {
    
// Get the arguments
    
$args func_get_args();
    
// Initialize parent with arguments
    
call_user_func_array(array('parent''__construct'), $args);
    
// ... Your Code Here ...
}
?>

Note that your constructor pass all the arguments to the parent constructor and it doesn't matter how many arguments you pass.

This is pretty useful for constructors with a variable number of arguments.

taylor (2005-06-02 05:51:53)

I came up with a better solution to the problem that I solve below with createObjArray that maintains parameter type:

<?php

function createObjArray($type,$args=array()) {
     
$paramstr '';
     for (
$i 0$i count($args); $i++) {
           
$paramstr .= '$args['.$i.'],';
     }
     
$paramstr rtrim($paramstr,',');

     return eval(
"return new $type($paramstr);");
}

?>

Would be good to add error checking, but it works.

taylor (2005-05-07 15:04:04)

<?php
    
/**
     * Create an object of a specified type using an array as the parameters
     * to the constructor.  NOTE: does not maintain proper 
     * types for the arguments.  They are all converted to strings.
     * @param $type Type type of object to create (class name)
     * @param $args The arguments to pass to the constructor
     */
    
function createObjArray($type$args=array()) {
        if ( !
class_exists($type) ) {
            return 
NULL;
        }
        
        
// build argument list; be sure to escape string delimeters
        
$func create_function('$str''return str_replace("\'","\\\'",$str);');
        
$sargs "'" join"','"array_map($func,$args) ). "'";
        
        
// build & eval code; return result
        
$seval "return new $type($sargs);";
        return eval(
$seval);
    }
?>

amer at o2 dot pl (2005-01-20 14:44:59)

PLS notice that "patripaq at hotmail dot com" 's code will be valid if B EXTENDS A...
<?php
class extends A{
...

?>
there>>"What I wanted to do is create an object that can manage any number and any kind of parameters."

BUT IT IS NOT A POINT AT ALL

If you need to call just function with parameters:
call_user_func_array('Foo',$args);

If you need to call CLASS method (NOT object):
call_user_func_array(array('class', 'Foo'),$args); 

If you need to call OBJECT method:
call_user_func_array(array(&$Object, 'Foo'),$args);

If you need to call method of object of object:
call_user_func_array(array(&$Object->Object, 'Foo'),$args);

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

The call_user_func_array ITSELF can manage any number and any kind of parameters. It can handle ANY FUNCTION too as it is defined and that maybe partipaq wanted to manage. 

What You actually need is object composition not inheritance. Make an instance from arguments. 
<?php
...
class 
B{
   function 
__construct() {
      
$args func_get_args(); // Get arguments
      
$this->OBJ = new A($args);
      
call_user_func_array(array(&$this->OBJ'A'), $args );
   }
}
?>
Then there can be any number and any type of created object B parameters

james at gogo dot co dot nz (2004-11-21 05:19:29)

Be aware the call_user_func_array always returns by value, as demonstrated here...

<?php    
    
function &foo(&$a)
    {
      return 
$a;
    }
    
    
$b 2;
    
$c =& call_user_func_array('foo', array(&$b));
    
$c++;
    echo 
$b ' ' $c;    
?>

outputs "2 3", rather than the expected "3 3".

Here is a function you can use in place of call_user_func_array which returns a reference to the result of the function call. 

<?php
    
function &ref_call_user_func_array($callable$args)
    {
        if(
is_scalar($callable))
        {
            
// $callable is the name of a function
            
$call $callable;
        }
        else
        {
            if(
is_object($callable[0]))
            {
                
// $callable is an object and a method name
                
$call "\$callable[0]->{$callable[1]}";
            }
            else
            {
                
// $callable is a class name and a static method
                
$call "{$callable[0]}::{$callable[1]}";
            }
        }
        
        
// Note because the keys in $args might be strings
        // we do this in a slightly round about way.
        
$argumentString = array();
        
$argumentKeys array_keys($args);
        foreach(
$argumentKeys as $argK)
        {
            
$argumentString[] = "\$args[$argumentKeys[$argK]]";
        }
        
$argumentString implode($argumentString', ');
        
// Note also that eval doesn't return references, so we 
        // work around it in this way...    
        
eval("\$result =& {$call}({$argumentString});");
        return 
$result;
    }
?>

php at pjt33 dot f2g dot net (2004-10-25 05:31:33)

Note that, although it doesn't say so here or in the linked page with information about the callback type, the changelog ( http://www.php.net/ChangeLog-4.php#4.0.5 ) states that call_user_func_array in PHP 4.0.4 won't take an array as the first argument. This was added in 4.0.5.

patripaq at hotmail dot com (2004-08-06 15:49:22)

I just started using PHP 5.0 and, so far, I'm loving it !  However, I had a problem the other day and thought it would be a good idea to inform other programmers about the solution I found to get around it.  It concerns the new __constructor() function and the call_user_func_array() function.  What I wanted to do is create an object that can manage any number and any kind of parameters.  Here's the problematic code:

<?php
//--------------------------
class {
  function 
__construct() {
    
$args func_get_args(); // Get arguments
    // Class initialization...
  
}
  function 
A() {
    
$args func_get_args(); // Get arguments
    
call_user_func_array( array(&$this'__construct'), $args ); // Infinite loop to B::__construct()...
  
}
}

class 
{
  function 
__construct() {
    
$args func_get_args(); // Get arguments
    
call_user_func_array( array(&$this'A'), $args ); // Initialize parent with arguments
    // Class initialization...
  
}
}

$obj = new B'param1''param2' );
//--------------------------
?>

I suppose you can guess where the problem is located... In the A::A() function, the call to __construct() using call_user_func_array() is redirected to B::__construct() instead of A::__construct().  The only way I found to specify which constructor function I wanted to call was to stop using A::__construct() and use the old fashion constructor instead.  If anyone can find a better way, feel free to add comments.  Here's my solution.  Hope it helps anyone.

<?php
//--------------------------
class {
  function 
A() {
    
$args func_get_args(); // Get arguments
    // Class initialization...
  
}
}

class 
{
  function 
__construct() {
    
$args func_get_args(); // Get arguments
    
call_user_func_array( array(&$this'A'), $args ); // Initialize parent with arguments
    // Class initialization...
  
}
}

$obj = new B'param1''param2' );
//--------------------------
?>

hong dot nguyen at k-edge dot com (2004-04-02 09:37:32)

call_user_func_array can pass parameters as reference:

<?php
call_user_func_array
(array(&$obj,$method),array(&$arg1,$arg2,$arg3))
?>

Use it as work-around for "Call-time pass-by-reference has been deprecated".

adamh at densi dot com (2003-07-31 11:58:32)

call_user_func_array() is nifty for calling PHP functions which use variable argument length. For example:

<?php
$array 
= array(
 array(
"foo""bar"),
 array(
"bat""rat"),
);

$values call_user_func_array("array_merge"$array);

var_dump($values);
?>

/* output:
array(4) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(3) "bat"
  [3]=>
  string(3) "rat"
}
*/

The neat feature is that $array could have any number of arrays inside it.

gord at fig dot org (2003-05-06 16:30:38)

If you need to call object and class methods in PHP < 4.0.4, the following code ought to do the trick:

<?php
if (!function_exists('call_user_func_array')) {
    function 
call_user_func_array($func$args)
    {
        
$argString '';
        
$comma '';
        for (
$i 0$i count($args); $i ++) {
            
$argString .= $comma "\$args[$i]";
            
$comma ', ';
        }

        if (
is_array($func)) {
            
$obj =& $func[0];
            
$meth $func[1];
            if (
is_string($func[0])) {
                eval(
"\$retval = $obj::\$meth($argString);");
            } else {
                eval(
"\$retval = \$obj->\$meth($argString);");
            }
        } else {
            eval(
"\$retval = \$func($argString);");
        }
        return 
$retval;
    }
}
?>

nutbar at innocent dot com (2003-03-12 12:29:52)

This function, combined with some others, can allow you to make some really easy & generic function macros (since real macros don't exist in PHP yet).

<?php
function my_printf() {
   
$args func_get_args();
   return 
call_user_func_array('printf'$args);
}
?>

This allows you to use my_printf() just as if it were printf() itself.  Very useful since you don't have to worry about how many arguments any functions take.

NOSPAM dot dont dot remove at thekid dot de (2002-06-22 16:19:51)

Unified constructors in PHP4:

<?php
  
class Object {
    function 
Object() {
      
$argsfunc_get_args();
      
call_user_func_array(array(&$this'__construct'), $args);
    }

    function 
__construct($argsNULL) {
      
var_dump($args);
    }
  }

  class 
Exception extends Object {
    var
      
$message;
      
    function 
__construct($message) {
      
$this->message$message;
      
parent::__construct();
    }
  }

  class 
IOException extends Exception {
  }
  
  
var_dump(
    
error_reporting(), 
    
zend_version(), 
    
phpversion()
  );
  
  
$c= new IOException('file not found');
  
  echo 
'===> Result: 'var_dump($c);
?>

易百教程