PHP 5.4调用时间传递引用 - 可以轻松修复?

bar*_*iir 215 php

有没有办法轻松解决这个问题,还是我真的需要重写所有遗留代码?

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

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

Tim*_*per 339

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

从文档:

函数调用上没有参考符号 - 仅在函数定义上.单独的函数定义足以通过引用正确传递参数.由于PHP 5.3.0中,你会得到一个警告说"呼叫时间传递通过引用"已经过时,当您使用&foo(&$a);.

例如,而不是使用:

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

使用:

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

  • 太糟糕了:( - 我从5.2移植到5.4,这真的很烦人...... (10认同)
  • 从PHP 5.0.0开始,弃用是那个给出`E_COMPILE_WARNING`级错误的时间,供参考:http://www.php.net/manual/en/ini.core.php#ini.allow-call-time-pass -参考 (9认同)
  • 对于注释中的人员,请注意删除&可能会导致意外结果,因为对变量的任何更改将不再共享,但只对函数本地范围可见.因此,除非您知道代码的作用,否则我建议按上述方法修复它,而不是仅删除&字符 (8认同)
  • 我有这个错误,但需要删除添加到变量的&insted. (5认同)
  • 我在旧代码中使用了一个名为event(&$ event)的对象,并且必须删除&符号以使错误消息消失. (2认同)

Pek*_*ica 7

对于像我这样的人来说这是因为他们需要将一个巨大的遗留项目更新为5.6:正如这里的答案所指出的那样,没有快速修复:你真的需要手动找到问题的每一个,并修复它.

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

使用这个正则表达式:

^(?!.*function).*(\&\$)
Run Code Online (Sandbox Code Playgroud)

可以在项目范围内搜索&$仅出现在非函数定义的行中.

这仍然会导致许多误报,但它确实使工作变得更容易.

VSCode的搜索结果浏览器可以让您轻松查找有问题的线条:您只需点击每个结果,然后查看linter下划线为红色的那些结果.你需要解决的问题.

  • 我正在使用更准确的正则表达式:`(?<!function)[:>] [a-zA-Z0-9 _] +(?<!foreach | array)\ s?\([^()]*\$` (3认同)

jgm*_*jgm 6

PHP和引用有点不直观.如果使用得当,在适当的位置引用可以提供大的性能改进或避免非常丑陋的变通方法和不寻常的代码.

以下将产生错误:

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

 function f($v){$v = true;}
 f(&$v);
Run Code Online (Sandbox Code Playgroud)

这些都不会失败,因为他们可以遵循以下规则,但毫无疑问已被删除或禁用,以防止许多遗留混乱.

如果它们确实有效,则两者都涉及冗余转换到引用,第二个也涉及冗余转换回范围包含的变量.

第二个过去可能允许将引用传递给不适用于引用的代码.这对于可维护性来说非常难看.

这无济于事:

 function f($v){$v = true;}
 $r = &$v;
 f($r);
Run Code Online (Sandbox Code Playgroud)

更具体地说,它将引用转回到正常变量,因为您没有要求引用.

这将有效:

 function f(&$v){$v = true;}
 f($v);
Run Code Online (Sandbox Code Playgroud)

这会看到您传递的是非引用但需要引用,因此将其转换为引用.

这意味着你不能将引用传递给一个函数,在这个函数中没有明确要求引用使它成为PHP严格传递类型的少数区域之一,或者在这种情况下更多的是元类型.

如果您需要更多动态行为,这将起作用:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);
Run Code Online (Sandbox Code Playgroud)

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