只能通过引用传递变量

时间:2010-06-03 15:50:46

标签: php error-handling variables reference

我有一个明智的想法,就是使用自定义错误处理程序,这导致我陷入了一个兔子洞。

以下代码给出(有和没有自定义错误处理程序):致命错误:只能通过引用传递变量

function foo(){
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

以下代码给出(仅使用自定义错误处理程序):(2048)只应通过引用传递变量

function foo(){
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a,-2,1));
    return $c;
}
print_r(foo());

第二个让我担心,因为我有很多'紧凑'的代码。所以,我要么放弃使用自定义错误处理程序(改进我的日志记录模块)或扩展我的所有代码的好主意。

任何有更好想法的人?还有,WTF?

更新

感谢答案,我已经了解了php如何处理错误。不包括E_STRICT(php 5)的E_ALL混淆并不酷。

除此之外,创建自己的自定义错误处理程序默认启用E_STRICT,以及问题开始的位置。

故事的寓意是使用你自己的错误处理程序来捕获它们并使用错误常量(E_STRICT,E_USER_WARNING,E_USER_ERROR等)进行过滤。

对于带有变量引用和某些函数的“内存损坏问题”,我能说什么?双重不冷静。我(这并不意味着你应该)在我的错误处理程序中忽略E_STRICT并继续生活。

8 个答案:

答案 0 :(得分:18)

array_pop()尝试更改作为参数传递的值。现在在第二个例子中,这是array_slice()的返回值。在引擎术语中,这是一个“临时值”,并且这样的值不能通过引用传递。你需要的是一个临时变量:

function foo(){
    $a=explode( '/' , 'a/b/c');
    $b=array_slice($a,-2,1);
    $c=array_pop($b);
    return $c;
}
print_r(foo());

然后可以将对$ b的引用传递给array_pop()。有关参考文献的详细信息,请参阅http://php.net/references

答案 1 :(得分:9)

在将error_reporting设置为E_ALL之后,在php-cli 中尝试第二个php代码片段时,我得到了以下内容。 E_STRICT

    gparis@techosaure:~/workspace/universcine.com$ php -a
Interactive shell

php > function foo(){
php {     $a=explode( '/' , 'a/b/c');
php {     $c=array_pop(array_slice($a,-2,1));
php {     return $c;
php { }
php > print_r(foo());
PHP Strict standards:  Only variables should be passed by reference in php shell code on line 3
PHP Stack trace:
PHP   1. {main}() php shell code:0
PHP   2. foo() php shell code:1

正如您所看到的,这里只有严格的标准。您可以轻松地让自定义错误处理程序忽略它们(基于您获得的值:例如,2048)。

从php 5.3开始,E_ALL不包含E_STRICT,请看:

php > foreach(array("E_ALL", "E_DEPRECATED", "E_STRICT", "E_NOTICE", "E_PARSE", "E_WARNING") as $const) echo $const . "  :\t" . constant($const) ."\t". decbin(constant($const)). "\n";
E_ALL  :        30719   111011111111111
E_DEPRECATED  : 8192     10000000000000
E_STRICT  :     2048       100000000000
E_NOTICE  :     8                  1000
E_PARSE  :      4                   100
E_WARNING  :    2                    10

从PHP 5.4开始,E_ALL确实包含E_STRICT

E_ALL  :            32767   111111111111111
E_DEPRECATED  :     8192     10000000000000
E_STRICT  :         2048       100000000000
E_NOTICE  :         8                  1000
E_PARSE  :          4                   100
E_WARNING  :        2                    10

答案 2 :(得分:4)

这是一个内存损坏问题(根据PHP开发团队的说法)。刚刚完成任务:

function foo(){
    $b = array_pop($arr = array("a","b","c"));
    return $b;
}
print_r(foo());

function foo(){
    $a = explode( '/' , 'a/b/c');
    $c = array_pop($arr = array_slice($a,-2,1));
    return $c;
}
print_r(foo());

第二个产生E_STRICT。如果您愿意,可以在错误处理程序中以不同方式处理(如果您不想更改这些函数)。

答案 3 :(得分:1)

array_pop()更改传递给它的值,这是错误的来源。功能无法更改。换句话说,您需要先将数组分配给变量(ref:manual),然后运行array_pop()

您需要的代码是:

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}

编辑:您提到的两个功能都存在同样的问题。将数组分配给变量并将变量传递给array_pop()

答案 4 :(得分:1)

我认为现在(因为php 5)它应该是:

function &foo(){ //NOTICE THE &
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

function &foo(){ //NOTICE THE &
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a, $b = -2, $c = 1)); //NOW NO DIRECT VALUES ARE PASSED IT MUST BE VARIABLES
    return $c;
}
print_r(foo());

但我只是一个乞丐:)

答案 5 :(得分:1)

我刚刚有了这种错误链接方法。

doSomething()->andThis()

我有:

doSomething()-andThis() // missing `>` character

我的情况有些复杂,但这是由于意外的subtraction操作造成的。

答案 6 :(得分:0)

试试这个:

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}

答案 7 :(得分:0)