Why does PHP allow passing a literal to the pass-by-reference parameter in one case, but not in the other?

The array_shift() function takes one parameter by reference. Passing an array literal causes a fatal error:

$ php -r 'var_export (array_shift (array ("Test # 0"));'; echo

Fatal error: only variables can be passed by reference in the command line on line 1

This is not as expected. However, PHP behaves strangely when a function is called using call_user_func_array:

 <?php var_export(call_user_func_array("array_shift", array(array("Test #1")))); echo "\n"; $arg1 = array("Test #2"); var_export(call_user_func_array("array_shift", array($arg1))); echo "\n"; $args = array(array("Test #3")); var_export(call_user_func_array("array_shift", $args)); echo "\n"; 

By doing:

$ php test.php

'Test # 1'

A warning. Parameter 1 is array_shift (), which must be a reference, the value specified in /Users/kcc/test.php on line 6 is NULL

A warning. Parameter 1 is array_shift (), which should be a reference, the value specified in /Users/kcc/test.php on line 10 NULL

It is clear that call_user_func_array() will not lead to a fatal error, but why does the first form work fine?

+5
source share
1 answer

From the document call_user_func_array () :

Prior to PHP 5.4, reference variables in param_arr are passed to the function by reference, regardless of whether the function expects the corresponding parameter by reference. This form of call forwarding by reference does not give a rejection notification, but nonetheless it is deprecated and was removed in PHP 5.4. In addition, this does not apply to internal functions for which the signature of the function is respected. Passing by value when a function expects a parameter by reference to lead to a warning and has call_user_func() return FALSE ( , however, there is an exception for the passed values ​​with reference count = 1, for example, in literals , since they can be turned into links without harmful effects - but also without writing to this value, which has any effect - but do not rely on this behavior, since the reference counter is an implementation detail, and the reliability of this behavior is doubtful).

(my emphasis)

Since PHP 5.4, call_user_func_array() passes all of its arguments to the value specified by $callback , except in the case in bold in the above quote.

In Test #1 , you have a pure literal, so you get the special exception described in the documentation: the literal can be turned into a link without any unwanted side effects (because it will just be thrown when call_user_func_array() is executed).

In Test #2 and Test #3 you do not have a pure literal, but because inside array_shift is defined as a parameter that takes it by reference, call_user_func_array() causes the warning described above.


In PHP 7, Test #1 is "fixed" and now correctly issues a warning.

+3
source

Source: https://habr.com/ru/post/1237293/


All Articles