为什么 PHP 在一种情况下允许将文字传递给按引用传递的参数,而在其他情况下则不允许?
Why does PHP allow passing a literal to a pass-by-reference parameter in one case but not others?
函数array_shift()
通过引用获取一个参数。传递数组文字会导致致命错误:
$ php -r 'var_export(array_shift(array("Test #0"));';echo
Fatal error: Only variables can be passed by reference in Command line code on line 1
这如预期的那样失败了。但是,当使用 call_user_func_array:
调用该函数时,PHP 表现异常
<?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";
执行时:
$ php test.php
'Test #1'
Warning: Parameter 1 to array_shift() expected to be a reference, value given in /Users/kcc/test.php on line 6
NULL
Warning: Parameter 1 to array_shift() expected to be a reference, value given in /Users/kcc/test.php on line 10
NULL
可以理解 call_user_func_array()
不会触发致命错误,但为什么第一种形式可以正常工作?
来自 call_user_func_array() 文档:
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).
(强调我的)
自 PHP 5.4 起,call_user_func_array()
将其所有参数按值传递给指定的 $callback
,除了上面手动引述中粗体显示的例外情况。
在 Test #1
中,你有一个纯文字,所以你遇到了文档中描述的特殊异常:文字可以变成一个没有不需要的 side-effects 的引用(因为它只会call_user_func_array()
完成后被丢弃。
在 Test #2
和 Test #3
中,您没有纯文字,因为在内部,array_shift
被定义为通过引用获取其参数,call_user_func_array()
引发上述警告。
在 PHP 7 中,Test #1
是 "fixed",现在可以正确发出警告。
函数array_shift()
通过引用获取一个参数。传递数组文字会导致致命错误:
$ php -r 'var_export(array_shift(array("Test #0"));';echo
Fatal error: Only variables can be passed by reference in Command line code on line 1
这如预期的那样失败了。但是,当使用 call_user_func_array:
调用该函数时,PHP 表现异常<?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";
执行时:
$ php test.php
'Test #1'
Warning: Parameter 1 to array_shift() expected to be a reference, value given in /Users/kcc/test.php on line 6 NULL
Warning: Parameter 1 to array_shift() expected to be a reference, value given in /Users/kcc/test.php on line 10 NULL
可以理解 call_user_func_array()
不会触发致命错误,但为什么第一种形式可以正常工作?
来自 call_user_func_array() 文档:
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 havingcall_user_func()
returnFALSE
(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).
(强调我的)
自 PHP 5.4 起,call_user_func_array()
将其所有参数按值传递给指定的 $callback
,除了上面手动引述中粗体显示的例外情况。
在 Test #1
中,你有一个纯文字,所以你遇到了文档中描述的特殊异常:文字可以变成一个没有不需要的 side-effects 的引用(因为它只会call_user_func_array()
完成后被丢弃。
在 Test #2
和 Test #3
中,您没有纯文字,因为在内部,array_shift
被定义为通过引用获取其参数,call_user_func_array()
引发上述警告。
在 PHP 7 中,Test #1
是 "fixed",现在可以正确发出警告。