1

在使用 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;

当第一次调用$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

小提琴:键盘@ Viper-7

在写这篇文章时,我想到了call_user_func_array()fiddle here,但产生了同样的错误。

我对引用有什么问题还是这是 PHP 的错误?

4

4 回答 4

8

我将其称为 PHP 的错误,尽管从技术上讲它是call_user_func. 文档确实提到了这一点,但可能不是以非常有启发性的方式:

请注意,for 的参数call_user_func()不是通过引用传递的。

可能更清楚地说,参数call_user_func()不是通过引用传递的(但请注意,从技术上讲,根本不需要说任何东西;这些信息也嵌入在函数签名中)。

无论如何,这意味着当call_user_func最终调用其目标可调用对象时,ZVAL正在传递的参数的(所有类型值的 PHP 引擎内部数据结构)不会被标记为“作为引用”;闭包在运行时检查它并抱怨,因为它的签名说参数必须是一个引用。

在 PHP < 5.4.0 中,可以通过使用调用时按引用传递来解决此问题:

 call_user_func($function, &$variable);

但这会产生一个E_DEPRECATED警告,因为调用时按引用传递是一个已弃用的功能,并且会在 PHP 5.4 中导致致命错误,因为该功能已被完全删除。

结论:这种方式没有很好的使用call_user_func方式。

于 2012-10-11T12:37:13.690 回答
3

这有效:

call_user_func_array($function, array(&$variable));
于 2012-10-12T01:33:21.997 回答
2

我用了这段代码

<?php
$myfunction = function &($arg=3)
{
    $arg = $arg * 2;
    return $arg;
};
echo $myfunction();
?>

像魅力一样工作。:)

于 2013-02-13T03:23:47.823 回答
1

如果你这样做会发生什么?

call_user_func($function, &$variable);
于 2012-10-11T12:39:23.257 回答