PHP匿名函数变量作为参考

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)

小提琴:Codepad @ Viper-7

在写这篇文章的时候,我想到了call_user_func_array():在这里小提琴,但是会产生同样的错误.

我有没有关于引用的错误或这是PHP的错误?

Jon*_*Jon 8

我会称这是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这种方式使用.

  • @Jon我不认为PHP 5.4中提供了通过引用传递的调用时间.你应该得到致命错误. (2认同)