【问题标题】:Only variables can be passed by reference只有变量可以通过引用传递
【发布时间】:2011-02-27 09:32:33
【问题描述】:

我有一个使用自定义错误处理程序的好主意,这让我陷入了困境。

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

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,然后生活继续。

【问题讨论】:

  • $b=current(array_reverse(array("a","b","c"))); // 是的,这很愚蠢,但它确实有效 :)

标签: php error-handling variables reference


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这是我在 php-cli 中尝试第二个 php 代码 sn-p 时得到的结果 在将 error_reporting 设置为 E_ALL | 之后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
    

    【讨论】:

    • 不,它没有,我编辑了我的帖子以添加解释性代码 sn-p。看到 E_ALL 中缺少的 1 了吗?如果添加 E_STRICT,则得到 111111111111111!意味着大奖!
    • 在 PHP 5.3 中 E_ALL 包含 E_STRICT
    • 不,但它会在 php 6 中。见这篇文章:stackoverflow.com/questions/1638238/…
    • 实际上,E_STRICT 已包含在 PHP 5.4 的 E_ALL 中(如该链接问题中所述)- 请参阅 PHP 手册:php.net/manual/en/errorfunc.constants.php - 但是,w3schools.com 仍然错误地报告它只是包含在 PHP 6 中。
    • @w3d :你说得对,我更新了我的答案,如果你发现错误,请自行更新。
    【解决方案3】:

    这是一个内存损坏问题(根据 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。如果您愿意(如果您不想更改这些函数),您可以在错误处理程序中以不同方式处理。

    【讨论】:

    • 我在某处看到了这个把戏。这适用于所有功能还是部分功能?
    • 您可以在任何函数中进行赋值。但不是在语言结构中,例如empty
    • 这严重阻碍了我的功夫。
    • 参数列表中的赋值是未定义的行为。 with array_pop($arr = array("a","b","c"));目前尚不清楚首先会发生什么 - $arr = array("a","b","c") 或 array_pop($arr) 或 array_pop(array("a","b","c")) ;并且可以在所有版本之间更改。
    • @johannes:你为什么这么说?
    【解决方案4】:

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

    你需要的代码是这样的:

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

    编辑:你提到的两个函数都有同样的问题。将数组赋值给一个变量并将变量传递给array_pop()

    【讨论】:

      【解决方案5】:

      我认为现在(从 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());
      

      但我只是一个初学者:)

      【讨论】:

      • 感谢您的回答。我没有时间尝试,但您是说添加“&”可以使其工作吗?它有什么作用?我明天去看看。
      【解决方案6】:

      试试这个:

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

      【讨论】:

        【解决方案7】:

        我刚刚得到了这个错误链接方法。

        doSomething()->andThis()
        

        我有:

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

        我的场景稍微复杂一些,但它源于意外的subtraction 操作。

        【讨论】:

          【解决方案8】:
          猜你喜欢
          • 2013-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-23
          • 2011-05-27
          • 2021-07-11
          相关资源
          最近更新 更多