php 从循环中的对象中删除项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7843157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 03:28:54  来源:igfitidea点击:

Removing an item from object in a loop

phploops

提问by Alex

I have a set of Db results that are stored in an object. I need to loop through the results and check a property (using another DB query) and then use an if statement to remove the item from the object. Here is a simplified version of what I'm attempting:

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

foreach ($products as $product) {

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

}
print_r($products);

However when I print_r the items are still in the object. I'm getting confused.

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

回答by realshadow

Thats expected behaviour. There are two main way of doing what you want

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

foreach ($products as $key => $product) {

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

}

Second way would be to use reference

第二种方法是使用参考

foreach ($products as &$product) {

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

}

回答by Mathieu Dumoulin

You need to understand that unsetting an object has no effect in php. First of all let me explain you a crucial detail with FOREACH:

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

if you do:

如果你这样做:

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

$a will be first copied in memory. Its not a brute copy per say, it only copies a reference to the data and augments the count of usage of the array(1,2,3,4,5) in memory. Inside of $b, you will have copies of the data found in $a. Therefore, unsetting it from memory only says, hey, unset $b from inside the copy of $a. Therefore, making no change at all in the real $a.

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

If you were to do:

如果你要这样做:

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

Then here you would have a copy of $a in memory. The Foreach would iterate (loop) on that copy and provide you with keys to each elements $a that gets copied into $b. When you unset($a[$key]) you tell php to affect the array in $a that got copied when the foreach started, but now, instead of affecting the copy, you are using the $key to reference an element in $a that truly exists in memory and that you will have access to.

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

Now for the second part, if we look at objects... unsetting an object has no effect because variables containing objects are only references to data in memory with a count. If you $a = new Object() and then $b = $a, you create a new reference to that object whilst keeping it intact (not copied).

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

If you were to unset($a), you would only unset the reference to the object and $b would still point to that object in memory. If you unset($b), you will then unset the object reference from memory because nothing points to it.

如果您要取消设置($a),您只会取消对对象的引用,而 $b 仍会指向内存中的该对象。如果您取消设置($b),那么您将从内存中取消设置对象引用,因为没有任何内容指向它。

Hope that makes it clearer...

希望能让它更清楚...

Good luck

祝你好运

回答by Alon Eitan

try this:

尝试这个:

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

回答by Jon

You can't unset the variable itself. You need to use the foreachsyntax that also gives you the item's key and use that to unset key on the array:

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

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

回答by Aurelio De Rosa

Use this line instead:

改用这一行:

foreach ($products as &$product)

回答by slevy1

Alternatively, you can change the loop from using a foreach and operate directly on the array using a for-loop as follows:

或者,您可以将循环从使用 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);

See live code.

查看实时代码