PHP 5.4 中的按引用传递调用时间 - 是否有简单的解决方法?

220

有没有简单的方法来解决这个问题,或者我真的需要重写所有旧代码吗?

PHP致命错误:在第30行已删除了按引用传递调用时间

这种情况在整个代码中到处发生,因为变量被作为引用传递到函数中。


3个回答

354
在函数定义中,应该使用按引用调用符号,而不是在实际调用中使用。由于PHP从版本5.3开始显示弃用错误,建议重写代码。

根据文档:

在函数调用时不需要使用引用符号——只需要在函数定义中使用即可。仅函数定义就足以正确地通过引用传递参数。自PHP 5.3.0起,当您在foo(&$a);中使用&时,将获得警告提示“call-time pass-by-reference”已被弃用。

例如,不要使用以下语句:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

使用:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }

9
自 PHP 5.0.0 开始,PHP 弃用了传递引用参数给函数的方式,并会产生 E_COMPILE_WARNING 错误等级的错误。参考链接:http://www.php.net/manual/en/ini.core.php#ini.allow-call-time-pass-reference - hakre
5
我遇到了这个错误,但需要将“&”删除而不是添加到变量中。 - Diana
2
我在旧代码中使用了一个名为event的对象(&$event),但是不得不移除&符号才能消除错误信息。 - Natalia
1
作为一名开发者,我多年来实际上从未需要在 PHP 中使用 & 符号。真的从来没有。这正是我正在寻找的。太棒了! - Juan Vilar
8
注意,评论区的读者们,删除 & 符号可能会导致意外的结果,因为对变量的任何更改将不再被共享,而只能在函数的局部范围内可见。因此,除非你知道代码的作用,我建议按照上述描述修复它,而不仅仅是删除 & 符号。 - xorinzor

8
对于像我一样需要将巨大的遗留项目更新到5.6版本的人来说(读者们),正如这里的答案所指出的,没有快速解决方案:你确实需要手动查找并修复每个问题的发生处。我在项目中发现的最方便的方法(除了使用完整的静态代码分析器,这非常准确,但我不知道有哪个可以立即带你到编辑器的正确位置)是使用Visual Studio Code。它内置了一个不错的PHP语言检测器和其搜索功能,允许通过正则表达式进行搜索。(当然,您可以使用任何支持PHP语言检测和正则表达式搜索的IDE/编辑器进行此操作。)使用以下正则表达式:
^(?!.*function).*(\&\$)

可以在整个项目中搜索&$出现的位置,但只限于非函数定义的行。

这仍然会有很多误报,但可以使工作变得更容易。

VSCode的搜索结果浏览器使得查找有问题的行变得超级简单:您只需点击每个结果并寻找由语法检查器用红色下划线标记的内容。这些需要修复。


1
这就是我一直在寻找的! - Sonny
4
我用于此目的的更准确的正则表达式是:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$ - Mojo
只需使用phpcs,它将为您挖掘每个包含此内容的文件。 - Thomas Cheng

6

PHP和引用有点不直观。如果在正确的地方适当使用引用,可以提供大量的性能改进或避免非常丑陋的解决方法和不寻常的代码。

以下代码将产生错误:

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

这些都不需要失败,因为它们可以遵循以下规则,但毫无疑问已被移除或禁用,以防止大量的旧代码混淆。

如果它们确实起作用,两者都涉及冗余转换为引用,第二个还涉及冗余转换回范围内包含变量。

第二种曾经是可能的,允许将引用传递给不打算使用引用的代码。这对于可维护性来说非常丑陋。

这将不会有任何作用:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

更具体地说,如果你没有请求引用,则将引用转换回普通变量。
这样做是可行的:
 function f(&$v){$v = true;}
 f($v);

这意味着您正在传递一个非引用参数,但想要一个引用参数,因此将其转换为引用参数。

这意味着您不能将引用参数传递给不明确要求引用参数的函数,这是PHP在传递类型方面严格的少数领域之一,或者更准确地说是元类型。

如果您需要更多动态行为,则可以使用以下方法:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

在这里,它看到你需要一个引用并且已经有了一个引用,所以不做任何更改。它可能会链接这个引用,但我怀疑这种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接