严格标准:只应通过引用传递变量

use*_*729 81 php reference strict

$el = array_shift($instance->find(..))
Run Code Online (Sandbox Code Playgroud)

上面的代码以某种方式报告了严格的标准警告,但这不会:

function get_arr(){
    return array(1,2);
}
$el = array_shift(get_arr());
Run Code Online (Sandbox Code Playgroud)

那么它什么时候会报告警告呢?

lee*_*ers 93

请考虑以下代码:

error_reporting(E_STRICT);
class test {
    function test_arr(&$a) {
        var_dump($a);   
    }
    function get_arr() {
        return array(1,2);  
    }
}

$t= new test;
$t->test_arr($t->get_arr());
Run Code Online (Sandbox Code Playgroud)

这将生成以下输出:

Strict Standards: Only variables should be passed by reference in `test.php` on line 14
array(2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}
Run Code Online (Sandbox Code Playgroud)

原因?该test::get_arr()方法不是变量,在严格模式下,这将生成警告.由于该get_arr()方法返回数组值,因此此行为非常不直观.

要在严格模式下解决此错误,请更改方法的签名,以便它不使用引用:

function test_arr($a) {
    var_dump($a);  
}
Run Code Online (Sandbox Code Playgroud)

由于您无法更改签名,array_shift您还可以使用中间变量:

$inter= get_arr();
$el= array_shift($inter);
Run Code Online (Sandbox Code Playgroud)

  • @ user198729:我正在寻找解释或修复,并发现你可以使用current()作为第一项.Alas end()不能用于最后一个,因为它"将内部指针前进到最后一个元素".current(array_reverse(somefunction()))有效(是的,很傻) (7认同)

Sag*_*agi 7

$instance->find() 返回对变量的引用.

当您尝试将此引用用作函数的参数时,可以获得报告,而不首先将其存储在变量中.

这有助于防止内存泄漏,并可能在下一个PHP版本中出错.

你写的第二个代码会抛出错误(注意&in函数签名):

function &get_arr(){
    return array(1,2);
}
$el = array_shift(get_arr());
Run Code Online (Sandbox Code Playgroud)

所以一个快速(并不那么好)的解决方案是:

$el = array_shift($tmp = $instance->find(..));
Run Code Online (Sandbox Code Playgroud)

基本上,您首先对临时变量进行赋值,并将变量作为参数发送.

  • 我尝试了你的第二个片段,没有工作.它只能在一个单独的行中工作 (4认同)
  • 确实.赋值*返回赋值*.`array_shift($ tmp = $ instance-> find(..))`将`$ instance-> find(..)`的值赋给`$ tmp`,然后将赋值*的*值传递给`array_shift ()` - 这与传递`$ tmp`本身不同,所以没有比没有赋值的原始情况更好. (3认同)

Bij*_*oor 6

错误的原因是使用内部PHP编程数据结构函数array_shift()[php.net/end].

该函数将数组作为参数.虽然array_shift()在"手册" 的原型中标明了&符号,但在该函数的扩展定义中没有注意事项,也没有任何明显的解释,该参数实际上是通过引用传递的.

也许这是/理解/.但是,我不明白,所以我很难找到错误的原因.

重现代码:

function get_arr()
{
 return array(1,2);
}
$array = get_arr();
$el = array_shift($array);
Run Code Online (Sandbox Code Playgroud)