【问题标题】:Removing an item from object in a loop在循环中从对象中删除项目
【发布时间】:2018-03-18 07:34:25
【问题描述】:

我有一组存储在对象中的 Db 结果。我需要遍历结果并检查一个属性(使用另一个数据库查询),然后使用 if 语句从对象中删除该项目。这是我正在尝试的简化版本:

foreach ($products as $product) {

    if(!$product->active) {
        unset($product);
    }

}
print_r($products);

但是,当我 print_r 时,项目仍在对象中。我越来越糊涂了。

【问题讨论】:

    标签: php loops


    【解决方案1】:

    这是预期的行为。有两种主要方法可以做你想做的事

    foreach ($products as $key => $product) {
    
        if(!$product->active) {
            unset($products[$key]);
        }
    
    }
    

    第二种方法是使用reference

    foreach ($products as &$product) {
    
        if(!$product->active) {
            unset($product);
        }
    
    }
    

    【讨论】:

    • 看起来与问题的代码相同。我很困惑,这就是答案。
    • @Dobler - 注意foreach ($products as &$product) 中的&。这意味着可以修改数据。
    • 在第一个示例中,它将是 unset($products[$key]);(带有尾随 s)。
    【解决方案2】:

    您需要了解取消设置对象在 php.ini 中没有任何影响。首先让我解释一下 FOREACH 的一个关键细节:

    如果你这样做:

    $a = array(1,2,3,4,5);
    foreach($a as $b){
        unset($b);
    }
    

    $a 将首先复制到内存中。它不是一个暴力复制,它只复制对数据的引用并增加内存中数组(1,2,3,4,5)的使用计数。在 $b 中,您将拥有在 $a 中找到的数据的副本。因此,从内存中取消设置它只是说,嘿,从 $a 的副本中取消设置 $b。因此,对真正的 $a 没有任何改变。

    如果你这样做:

    $a = array(1,2,3,4,5);
    foreach($a as $key => $b){
        unset($a[$key]);
    }
    

    那么这里你会在内存中有一个 $a 的副本。 Foreach 将在该副本上进行迭代(循环),并为您提供复制到 $b 中的每个元素 $a 的键。当你 unset($a[$key]) 你告诉 php 影响在 foreach 开始时复制的 $a 中的数组,但是现在,不是影响副本,而是使用 $key 来引用 $ 中的元素一个真正存在于内存中并且你可以访问的。

    现在对于第二部分,如果我们查看对象...取消设置对象没有任何效果,因为包含对象的变量只是对内存中具有计数的数据的引用。如果 $a = new Object() 然后 $b = $a,则创建对该对象的新引用,同时保持其完整(未复制)。

    如果你要取消设置($a),你只会取消对对象的引用,而 $b 仍然会指向内存中的那个对象。如果你取消设置($b),你就会从内存中取消设置对象引用,因为没有任何东西指向它。

    希望它更清楚......

    祝你好运

    【讨论】:

      【解决方案3】:

      您不能取消设置变量本身。您需要使用foreach 语法,该语法还为您提供项目的密钥并使用它来取消设置数组上的密钥:

      foreach ($products as $key => $product) {
          if(!$product->active) {
              unset($products[$key]);
          }
      }
      

      【讨论】:

        【解决方案4】:

        改用这一行:

        foreach ($products as &$product)
        

        【讨论】:

          【解决方案5】:

          试试这个:

          // $id is the key, $product is the value
          foreach ($products as $id => $product) {
              if(!$product->active) {
                  unset($products[$id]);
              }
          }
          

          【讨论】:

            【解决方案6】:

            或者,您可以将循环从使用 foreach 更改为使用 for 循环直接对数组进行操作,如下所示:

            <?php
            
            $o1 = new stdClass;
            $o2 = new stdClass;
            $o3 = new stdClass;
            
            $o1->active = false;
            $o2->active = true;
            $o3->active = true;
            
            
            $products = [$o1, $o2, $o3];
            
            
            for($i=0, $max=count($products); $i < $max; $i++) {
                    if (!($products[$i]->active)) {
                        unset($products[$i]);
                    }
            }
            print_r($products);
            
            // re-index:
            
            $improvedProducts = array_values($products);
            print_r($improvedProducts);
            

            live code

            【讨论】:

              猜你喜欢
              • 2011-11-17
              • 2013-04-22
              • 1970-01-01
              • 2012-03-30
              • 2020-06-24
              • 2011-03-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多