Parameters

Return Values

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

Changelog

Version

Description

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.

Notes

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:

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

User Contributed Notes 41 notes

Please note, that when calling call_user_func_array() to redirect parameters between inherited classes, you should not use $this, because $this always refers to the class which has been instantiated. The following code even seems to crash PHP (PHP does not report error but the process simply terminates), because the the parameters are redirected only one level up (to class foo_bar2):

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 '.$function, E_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);}?>

PLS notice that "patripaq at hotmail dot com" 's code will be valid if B EXTENDS A...<?phpclass B 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

Benchmarks from https://gist.github.com/nikic/6390366cufa with 0 args took 0.43453288078308switch with 0 args took 0.24134302139282unpack with 0 args took 0.12418699264526cufa with 5 args took 0.73408579826355switch with 5 args took 0.49595499038696unpack with 5 args took 0.18640494346619cufa with 100 args took 5.0327250957489switch with 100 args took 5.291127204895unpack with 100 args took 1.2362589836121

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.

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

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.

<?phpfunction &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; }?>

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:

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.

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.

I recently had<?php call_user_func_array('MyClass::myFunction', array(0, 10));?>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(0, 10));?>

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