jol*_*olt 1 php reference function anonymous-function
在使用Laravel框架时,更具体的 - 表单宏,我偶然发现了一个奇怪的错误.
起初,我认为Laravel有点不对劲,但后来我把所有东西都脱离了背景:
<?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;
Run Code Online (Sandbox Code Playgroud)
第一次$function正确执行调用时,第二次尝试使用call_user_func(),生成(摘自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
Run Code Online (Sandbox Code Playgroud)
在写这篇文章的时候,我想到了call_user_func_array():在这里小提琴,但是会产生同样的错误.
我有没有关于引用的错误或这是PHP的错误?
我会称这是PHP的一个错误,虽然它在技术上是一个错误call_user_func.文档确实提到了这一点,但也许不是一个非常有启发性的方式:
请注意,参数
call_user_func()不通过引用传递.
或许可以更清楚地说,参数call_user_func()不是通过引用传递的(但请注意,从技术上讲,没有必要说任何东西;这些信息也嵌入在函数签名中).
在任何情况下,这意味着当call_user_func最终调用其目标可调用时,ZVAL传递的参数的(所有类型的值的PHP引擎内部数据结构)不会被标记为"正在引用"; 闭包在运行时检查它并抱怨,因为它的签名表明参数必须是引用.
在PHP <5.4.0中,可以通过引用使用call-time传递来解决此问题:
call_user_func($function, &$variable);
Run Code Online (Sandbox Code Playgroud)
但这会产生一个E_DEPRECATED警告,因为通过引用传递的调用时间是一个不推荐使用的功能,并且将在PHP 5.4中导致致命错误,因为该功能已被完全删除.
结论:没有好的方法可以call_user_func这种方式使用.