【问题标题】:How to avoid undefined offset如何避免未定义的偏移量
【发布时间】:2011-07-04 21:47:01
【问题描述】:

如何轻松避免收到此错误/通知:

Notice: Undefined offset: 1 in /var/www/page.php on line 149

...在这段代码中:

list($func, $field) = explode('|', $value);

explode 并不总是返回两个值,但是如果你想使用 list() 怎么能轻松避免通知呢?

【问题讨论】:

    标签: php


    【解决方案1】:
    list($func, $field) = array_pad(explode('|', $value, 2), 2, null);
    

    两个变化:

    • 它将explode() 返回的数组的大小限制为2。看来,仅此而已
    • 如果返回的值少于两个,它会追加null,直到数组包含两个值。更多信息请见Manual: array_pad()

    这意味着,如果$value 中没有|,则$field === null。当然,您可以使用您喜欢定义为$field 的默认值(而不是null)。也可以交换$func$field 的行为

    list($func, $field) = array_pad(explode('|', $value, 2), -2, null);
    

    现在$funcnull,而$value 中没有|

    【讨论】:

      【解决方案2】:

      这对我有用:

      @list($func, $field) = explode('|', $value);
      

      【讨论】:

      • 我同意你的看法@bart。在大多数情况下确实如此,但在这种特定情况下,我看不出不使用它的主要问题。
      【解决方案3】:

      我相信,当你试图通过 ($value) 分解字符串的东西实际上并没有包含它时,你会得到一个 undefined offset

      这个问题与此非常相似: undefined offset when using php explode(),这里有更进一步的解释,应该可以完全解决您的问题。

      关于检查'|'的出现为了防止错误,您可以这样做:

      $pos = strpos($value,'|');
      
      if(!($pos === false)) {
           //$value does contain at least one |
      }
      

      希望这会有所帮助。

      【讨论】:

      • @Down Voter 您介意解释一下原因吗?如果我犯了错误,我不会被否决,如果你能解释为什么我可以更正帖子并从我出错的地方学习!干杯。
      • 即使strpos 返回true,您仍然会出错。 $value = 'almost|perfect'; $pos = strpos($value,'|'); if ($pos === true) { list($one, $two, $three) = explode('|', $value); }
      【解决方案4】:

      我可能会将其分为两个步骤

      $split = explode('|', $value);
      $func = $split[0];
      if(count($split) > 1)
        $field = $split[1];
      else
        $field = NULL;
      

      不过可能有一种更快更简洁的方法。

      【讨论】:

      • 这将使$field 未定义,这几乎比未定义的索引更好。
      • 是的,你是对的。我添加了一行将其设置为 NULL,以防它之前已定义。但无论如何,我认为您需要在使用 $field 之前检查它的值。
      【解决方案5】:
      if (count(explode('|', $value))==2)
        list($func, $field) = explode('|', $value);
      

      但它不是最佳的。

      【讨论】:

      • 爆炸两次?为什么不只检测是否有管道字符,然后爆炸?
      【解决方案6】:

      我经常遇到这个问题,所以我想要一个函数,它允许在语法上更好的东西,而无需不必要地填充数组或字符串。

      // Put array entries in variables. Undefined index defaults to null
      function toVars($arr, &...$ret)
      {
          $n = count($arr);
          foreach ($ret as $i => &$r) {
              $r = $i < $n ? $arr[$i] : null;
          }
      }
      
      // Example usage
      toVars(explode('|', $value), $func, $field);
      

      出于我的目的,我通常使用数组,但您可以编写一个包含explode函数的类似函数,如下所示...

      // Explode and put entries in variables. Undefined index defaults to null
      function explodeTo($delimiter, $s, &...$ret)
      {
          $arr = explode($delimier, $s);
          $n = count($arr);
          foreach ($ret as $i => &$r) {
              $r = $i < $n ? $arr[$i] : null;
          }
      }
      
      // Example usage
      toVars('|', $value, $func, $field);
      

      可变参数功能需要 PHP5.6 或以上版本: http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list

      【讨论】:

        【解决方案7】:

        想提一下我几十年来一直在使用的更通用的效用函数。它过滤掉空值并修剪空格。它还使用array_pad() 来确保您至少获得所需数量的值(如@KingCrunch 所建议的那样)。

        /**
         * Does string splitting with cleanup.
         * Added array_pad() to prevent list() complaining about undefined index
         * @param $sep string
         * @param $str string
         * @param null $max
         * @return array
         */
        function trimExplode($sep, $str, $max = null)
        {
            if ($max) {
                $parts = explode($sep, $str, $max); // checked by isset so NULL makes it 0
            } else {
                $parts = explode($sep, $str);
            }
            $parts = array_map('trim', $parts);
            $parts = array_filter($parts);
            $parts = array_values($parts);
            $parts = array_pad($parts, $max, null);
            return $parts;
        }
        

        【讨论】:

          【解决方案8】:

          我不知道有一种直接的方法来做到这一点,同时也保留了

          的便利性
          list($func, $field) = explode('|', $value);
          

          但是,由于能够做到这一点真的很遗憾没有,您可能需要考虑一种偷偷摸摸的间接方法:

          list($func, $field) = explode('|', $value.'|');
          

          我已根据需要向$value 添加了尽可能多的|s,以确保explode 将在数组中生成至少2 个项目。对于n 变量,添加n-1 分隔符。

          这样你不会得到任何错误,你保持方便的list赋值,输入中不存在的任何值都将被设置为空字符串。在大多数情况下,后者应该不会给您带来任何问题,因此上述想法会奏效。

          【讨论】:

          • 如果只是为了“不显示”通知,我们不能通过 @explode() 来压制它吗?我知道它不漂亮,但它确实有用吗?如果你真的想“避免”它,那么你是绝对正确的......
          • @KilZone:这并不是真的“不显示”它,而是“这段代码的编写方式是,如果它出现错误,它就会产生错误”。此外,如果可能,最好避免使用 @ 运算符。您知道运营商文档中的that warning 吗?我不止一次为此而堕落。
          • 好吧,我明白你(和 clarkk 的)观点,我只是想知道。哦,是的,我知道这个警告,这不是我第一次盯着我的页面应该在的空白屏幕。
          • 确实,很可惜!他们在想什么... :-(
          猜你喜欢
          • 1970-01-01
          • 2013-08-18
          • 2011-03-13
          • 1970-01-01
          • 2020-02-10
          • 2022-01-02
          • 2013-01-25
          • 2011-07-22
          相关资源
          最近更新 更多