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

时间:2010-03-01 08:35:55

标签: php reference strict

$el = array_shift($instance->find(..))

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

function get_arr(){
    return array(1,2);
}
$el = array_shift(get_arr());

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

6 个答案:

答案 0 :(得分: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());

这将生成以下输出:

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

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

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

function test_arr($a) {
    var_dump($a);  
}

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

$inter= get_arr();
$el= array_shift($inter);

答案 1 :(得分:8)

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

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

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

如果第二个代码写得像(注意& in function signature),那么你的第二个代码会抛出错误:

function &get_arr(){
    return array(1,2);
}
$el = array_shift(get_arr());

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

$el = array_shift($tmp = $instance->find(..));

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

答案 2 :(得分:5)

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

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

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

重现代码:

function get_arr()
{
 return array(1,2);
}
$array = get_arr();
$el = array_shift($array);

答案 3 :(得分:3)

第二个片段也不起作用,这就是原因。 array_shift是一个修饰符函数,它改变了它的参数,因此它希望它的参数是一个引用,你不能引用一个不是变量的东西。请参阅Rasmus在此处的解释:Strict standards: Only variables should be passed by reference

答案 4 :(得分:3)

此代码:

$monthly_index = array_shift(unpack('H*', date('m/Y')));

需要改为:

$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);

答案 5 :(得分:-1)

嗯,在这种明显的情况下,你总是可以告诉PHP使用" @"来抑制消息。在功能面前。

$monthly_index = @array_shift(unpack('H*', date('m/Y')));

以这种方式抑制所有错误可能不是最好的编程实践之一,但在某些情况下(比如这个)它很方便且可以接受。

结果,我相信你的朋友SysAdmin会对污染较少的" error.log"感到满意。 ;)