【问题标题】:Skipping insert if array item is not found?如果找不到数组项,则跳过插入?
【发布时间】:2016-04-10 12:55:37
【问题描述】:

我目前正在将来自 json api url 的数据插入到我的数据库中,但某些数组未完成填写导致“未定义索引”错误。

有什么好的方法来解决这个问题吗?当然,使用 if isset 语句检查每个项目索引并仅在可用时设置它会起作用,但对于每个条目来说这将是相当乏味的。

        foreach($items['response']['groups'] as $item) {
            foreach($item['items'] as $item) {
                Bar::firstOrCreate([
                    'lat' => $item['venue']['location']['lat'],
                    'long' => $item['venue']['location']['lng'],
                    'postalCode' => $item['venue']['location']['postalCode'],
                    'city' => $item['venue']['location']['city'],
                    'state' => $item['venue']['location']['state'],
                    'country' => $item['venue']['location']['country'],
                    'address' => $item['venue']['location']['address'],
                    'rating' => $item['venue']['rating'],
                    'website' => $item['venue']['url'],
                ]);
            }
        }

【问题讨论】:

  • 您可以通过在每个数组键上使用 isset() 来测试每个数组的完整性。或者只是通过使用@$item[...][...] 来抑制有关未定义索引的任何警告,这不是很优雅,但可能会解决您的问题。
  • 使用isset()有什么不好的地方?
  • isset 工作正常,但在我看来,当您使用 API 时,这是一个反复出现的问题,我想知道 laravel 是否可以开箱即用地帮助解决这个问题。

标签: php arrays eloquent laravel-5.1


【解决方案1】:

您的问题是您在每次迭代时重写 $item 的值。

foreach($items['response']['groups'] as $item) {
    foreach($item['items'] as $item) {
        // after first iteration here `$item` doesn't have `items` key
    }

在每个foreach 中使用不同的变量。

【讨论】:

    【解决方案2】:

    您必须在某处检查索引是否存在!如果您不想在控制器中执行此操作,则可以有一个类似检查每个字段的实体:

    <?php
    class MyEntity 
    {
    
        private $lat;
        private $long;
        private $postalcode;
        ...
    
        public static function createInstanceFromArray(array $item)
        {
            if (isset($item['lat']) {
                $this->setLat($item['lat']);
            }
            ... and so on
    
            // you could also do it automatic :
            foreach($item as $key => $value) {
                $methodName = 'set' . ucfirst($key);
                if (method_exists($this, $methodName)) {
                    $this->{$methodName}($value);
                }
            }
        }
    
        public function setLat($lat) 
        {
            $this->lat = $lat;
    
            return $this;
        }
    
        public function getLat()
        {
            return $this->lat;
        }
    }
    

    然后您可以对原始代码执行以下操作:

    foreach($items['response']['groups'] as $item) {
        foreach($item['items'] as $subItem) {
            $myEntity = MyNamespace\MyEntity::cretaInstanceFromArray($subItem['venue']);
        }
    }
    

    然后您可以使用您的方法设置实体的字段:

    'lat' => $myEntity->getLat();
    ....
    

    这样,即使数组字段不存在,实体也会返回一个默认值。

    如果你不想使用对象,你可以使用带有默认值的 array_merge 来确保你不会有 undefindex 索引:

    $item = array_merge([
        'lat' => '',
        'long' => '',
        'postalCode' => '',
        ...
    ], $item['venue']);
    

    例如,将该处理放在一个函数中。

    【讨论】:

      【解决方案3】:

      检查每个数组的完整性,如果真的完整则只检查Bar::firstOrCreate()

      foreach($items['response']['groups'] as $item) {
      
       foreach($item['items'] as $item) {
              if(
                  isset($item['venue']) &&
                  isset($item['venue']['location']) &&
                  isset($item['venue']['location']['lat']) &&
                  isset($item['venue']['location']['lng']) &&
                  isset($item['venue']['location']['postalCode']) &&
                  isset($item['venue']['location']['city']) &&
                  isset($item['venue']['location']['state']) &&
                  isset($item['venue']['location']['country']) &&
                  isset($item['venue']['location']['address']) &&
                  isset($item['venue']['location']['lng']) &&
                  isset($item['venue']['rating']) &&
                  isset($item['venue']['url'])
              )
          Bar::firstOrCreate([
              'lat' => $item['venue']['location']['lat'],
              'long' => $item['venue']['location']['lng'],
              'postalCode' => $item['venue']['location']['postalCode'],
              'city' => $item['venue']['location']['city'],
              'state' => $item['venue']['location']['state'],
              'country' => $item['venue']['location']['country'],
              'address' => $item['venue']['location']['address'],
              'rating' => $item['venue']['rating'],
              'website' => $item['venue']['url'],
          ]);
        }
      }
      

      【讨论】:

        【解决方案4】:

        你可以使用这些简单的步骤

        1. 从嵌套数组中删除所有不包含值的键,然后
        2. 删除所有空的嵌套数组。

          $yourArray= array_map('array_filter', $yourArray);

          $yourArray= array_filter($yourArray);

        【讨论】:

          【解决方案5】:

          使用最简单的方法,例如:

          foreach($items['response']['groups'] as $item1) {
                      foreach($item1['items'] as $item) {
                          Bar::firstOrCreate([
                              'lat' => isset($item['venue']['location']['lat'])?$item['venue']['location']['lat'] : '',
                              'long' => isset($item['venue']['location']['lng'])?$item['venue']['location']['lng'] : '',
                              'postalCode' => isset($item['venue']['location']['postalCode'])?$item['venue']['location']['postalCode'] : '',
                              'city' => isset($item['venue']['location']['city'])?$item['venue']['location']['city'] : '',
                              'state' => isset($item['venue']['location']['state'])?$item['venue']['location']['state'] : '',
                              'country' => isset($item['venue']['location']['country'])?item['venue']['location']['country'] : '',
                              'address' => isset($item['venue']['location']['address'])?$item['venue']['location']['address'] : '',
                              'rating' => isset($item['venue']['rating'])?$item['venue']['rating'] : '',
                              'website' => isset($item['venue']['url'])?$item['venue']['url'] : '',
                          ]);
                      }
                  }
          

          【讨论】:

          • 您是否看到在第一个和第二个foreach OP 中都使用$item 作为可迭代值?你不认为在第一次内部 foreach 迭代之后 $item 将不再是第一次迭代之前的样子吗?
          猜你喜欢
          • 2015-12-02
          • 2014-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-09
          • 1970-01-01
          • 2021-03-11
          • 2021-06-03
          相关资源
          最近更新 更多