Pass by reference and call_user_func and php 5.4

pre 5.4, this code:

$a = array( '1' => 1 );
function test(&$a) {
	$a['2'] = 2;
}
call_user_func('test',&$a);
print_r($a);

gives

Array
(
    [1] => 1
    [2] => 2
)

without the & in call_user_func(‘test’,&$a); it’s:

Array
(
    [1] => 1
)

In php 5.4 you can’t use & in the code above’s way. Only in function declarations, in the arguments list after the function name.
The first bit of code above, in 5.4, gives:
Fatal error: Call-time pass-by-reference has been removed in …

So how can I pass by reference when using call_user_func ?

Just remove & here:

call_user_func('test',&$a);

and leave it only in the function declaration.
Everything will work again.

No, that’s just it, it behaves like pre 5.4 without the & in the call_user_func(‘test’,&$a) line. That is it modifies the array in the function but the changes don’t make it out of the function, so the example bit of code results in

Array ( [1] => 1 )
which isn’t what I’m after.

So just to be clear, in 5.4, this:

$a = array( '1' => 1 );
function test(&$a) {
	$a['2'] = 2;
}
call_user_func('test',$a);
print_r($a);

gives

Array ( [1] => 1 )
and this warning:
Warning: Parameter 1 to test() expected to be a reference, value given in …

Depending on what you intend the function to do return http://php.net/manual/en/function.return.php might be what you need

call_user_func says, “the parameters for call_user_func() are not passed by reference.” So it looks like they screwed you on that one. A couple other options are:

Call function through variable:

$func = 'test';
$func($a);

Or wrap array in an object, because objects are always passed by reference:

$obj = new stdClass();
$obj->a = array( '1' => 1 );
function test($obj) {
    $obj->a['2'] = 2;
}
call_user_func('test',$obj);
print_r($obj->a);

Or… and this is worth a try… use ordinary pass and return by value.

$a = array( '1' => 1 );
function test($a) {
    $a['2'] = 2;
    return $a;
}
$a = call_user_func('test',$a);
print_r($a);

PHP might be smart enough to optimize this case, and whatever performance penalty you’re trying to avoid might not exist in the first place. It’s worth benchmarking to be sure before you go further into more complex solutions.

The wrapping the array in an object is the way I’m going to go. Modifying the call_user_func bit isn’t so good as in the actual code I’m using ParallelCurl is part of it and the call_user_func bit is part of that, not my code, so want to leave that alone.

Great, thanks for that.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.