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.
source share