While working with Laravel framework, more specific – Form macros, I stumbled upon a weird error.
At first, I thought it’s something wrong with Laravel, but then I took everything out of context:
<?php
// placeholder function that takes variable as reference
$function = function(&$reference)
{
// append to variable
$reference = $reference . ':' . __METHOD__;
};
// test with straight call
$variable = 'something';
$function($variable);
echo $variable;
// test with call_user_func(), that gets called in Laravels case
$variable = 'something'; // reset
call_user_func($function, $variable);
echo $variable;
While the first call to $function executes properly, the second try with call_user_func(), produces (excerpt from Codepad):
Warning: Parameter 1 to {closure}() expected to be a reference, value given
PHP Warning: Parameter 1 to {closure}() expected to be a reference, value given
Fiddle: Codepad @ Viper-7
While writing this, I thought about call_user_func_array(): fiddle here, but the same error is produced.
Have I got something wrong about references or is this a bug with PHP?
I would call this a bug with PHP, although it’s technically a bug with
call_user_func. The documentation does mention this, but perhaps not in a very enlightening way:It would be perhaps clearer to say that the arguments to
call_user_func()are not passed by reference (but note that technically it’s not necessary to say anything at all; this information is also embedded in the function signature).In any case, this means is that when
call_user_funcfinally gets to invoking its target callable, theZVAL(PHP engine internal data structure for all types of values) for the argument being passed is not marked as “being-a-reference”; the closure checks this at runtime and complains because its signature says that the argument must be a reference.In PHP < 5.4.0 it is possible to work around this by using call-time pass by reference:
but this produces an
E_DEPRECATEDwarning because call-time pass by reference is a deprecated feature, and will flat out cause a fatal error in PHP 5.4 because the feature has been removed completely.Conclusion: there is no good way to use
call_user_funcin this manner.