Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从循环中的对象中删除项_Php_Loops - Fatal编程技术网

Php 从循环中的对象中删除项

Php 从循环中的对象中删除项,php,loops,Php,Loops,我有一组存储在对象中的Db结果。我需要遍历结果并检查属性(使用另一个DB查询),然后使用if语句从对象中删除该项。以下是我尝试的简化版本: foreach ($products as $product) { if(!$product->active) { unset($product); } } print_r($products); 但是,当我打印时,项目仍在对象中。我感到困惑。试试这个: // $id is the key, $product is

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

foreach ($products as $product) {

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

}
print_r($products);
但是,当我打印时,项目仍在对象中。我感到困惑。

试试这个:

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

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

foreach ($products as $key => $product) {
    if(!$product->active) {
        unset($products[$key]);
    }
}
请改为使用此行:

foreach ($products as &$product)

这是预期的行为。做你想做的事情主要有两种方式

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

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

}
第二种方法是使用


您需要了解,在php中取消设置对象没有任何效果。首先,让我向您解释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 = array(1,2,3,4,5);
foreach($a as $key => $b){
    unset($a[$key]);
}
那么在这里,你将有一个$a的副本在内存中。Foreach将对该副本进行迭代(循环),并向您提供复制到$b中的每个元素$a的键。当您取消设置($a[$key])时,您告诉php影响foreach启动时复制的$a中的数组,但现在,您使用$key引用$a中确实存在于内存中且您将有权访问的元素,而不是影响副本

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

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

希望这能让事情变得更清楚


祝您好运

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

看起来与问题的代码相同。我很困惑这就是答案。@Dobler-注意
foreach($products as&$product)
中的
&
。这意味着可以修改数据。在第一个示例中,它将是
unset($products[$key])(带尾随的s)。
<?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);