【问题标题】:PHP 5.4 Call-time pass-by-reference - Easy fix available?PHP 5.4 Call-time pass-by-reference - 可以轻松修复吗?
【发布时间】:2012-02-16 18:43:59
【问题描述】:

有什么方法可以轻松解决这个问题,还是我真的需要重写所有遗留代码?

PHP 致命错误:在第 30 行的 ... 中删除了调用时传递引用

这种情况随处可见,因为变量在整个代码中作为引用传递给函数。

【问题讨论】:

标签: php


【解决方案1】:

您应该在函数定义中通过引用来表示调用,而不是实际调用。由于 PHP 在 5.3 版本中开始显示弃用错误,我会说重写代码是个好主意。

From the documentation:

函数调用没有引用符号 - 仅在函数定义上。 仅函数定义就足以通过引用正确传递参数。从 PHP 5.3.0 开始,当您在 foo(&$a); 中使用 & 时,您将收到一条警告,指出“调用时传递引用”已被弃用。

例如,不要使用:

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

用途:

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

【讨论】:

  • 自 PHP 5.0.0 起弃用,回溯到 E_COMPILE_WARNING 级别错误,供参考:php.net/manual/en/…
  • 我遇到了这个错误,但需要删除添加到变量的 & insted。
  • 我在旧代码中将它用于一个名为 event (&$event) 的对象,并且必须删除 & 符号才能使错误消息消失。
  • 在我作为开发人员的所有这些年里,我实际上从未需要在 php 上使用 &。永远不能。这正是我想要的。很棒
  • 对于 cmets 中的人员,请注意删除 & 可能会导致意外结果,因为对变量的任何更改将不再共享,而仅对函数本地范围可见。因此,除非您知道代码的作用,否则我建议您按照上述方法修复它,而不是仅仅删除 & 字符
【解决方案2】:

对于像我一样因为需要将大型遗留项目更新到 5.6 而阅读此内容的任何人:正如此处的答案所指出的,没有快速解决方法:您确实需要手动查找每次出现的问题,并修复它。

我发现找到项目中所有有问题的行的最方便的方法(没有使用成熟的静态代码分析器,它非常准确,但我不知道有任何方法可以将您带到编辑器中的正确位置马上)正在使用 Visual Studio Code,它内置了一个很好的 PHP linter,它的搜索功能允许通过 Regex 进行搜索。 (当然,您可以使用任何执行 PHP linting 和 Regex 搜索的 IDE/代码编辑器。)

使用这个正则表达式:

^(?!.*function).*(\&\$)

只能在不是函数定义的行中搜索项目范围内出现的&$

这仍然会出现很多误报,但确实让工作变得更容易。

VSCode 的搜索结果浏览器使浏览和查找违规行变得非常容易:您只需单击每个结果,并注意那些 linter 用红色下划线的那些。那些你需要修复的。

【讨论】:

  • 这就是我要找的东西!
  • 我为此目的使用的更准确的正则表达式:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
  • 只要使用 phpcs,它会为你挖掘出每个有这个的文件。
【解决方案3】:

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);

在这里它看到你想要一个参考并且已经有一个参考所以不要管它。它也可能链接引用,但我对此表示怀疑。

【讨论】:

    猜你喜欢
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 2016-11-15
    相关资源
    最近更新 更多