我有一组存储在对象中的Db结果。我需要遍历结果并检查属性(使用另一个数据库查询),然后使用if语句从对象中删除项目。这是我正在尝试的简化版本:
foreach ($products as $product) {
if(!$product->active) {
unset($product);
}
}
print_r($products);
然而,当我print_r时,项目仍在对象中。我很困惑。
答案 0 :(得分:12)
这是预期的行为。做你想做的事有两种主要方式
foreach ($products as $key => $product) {
if(!$product->active) {
unset($products[$key]);
}
}
第二种方式是使用reference
foreach ($products as &$product) {
if(!$product->active) {
unset($product);
}
}
答案 1 :(得分:3)
您需要了解取消设置对象对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中根本不做任何改变。
如果你这样做:
$a = array(1,2,3,4,5);
foreach($a as $key => $b){
unset($a[$key]);
}
然后在这里你会得到$ a的内存副本。 Foreach将对该副本进行迭代(循环),并为每个元素$ a提供密钥,将其复制到$ b中。当你取消设置($ a [$ key])时,你告诉php影响在foreach启动时复制的$ a中的数组,但是现在,你使用$ key来引用$中的元素而不是影响副本。一个真正存在于内存中的,你将有权访问。
现在对于第二部分,如果我们查看对象...取消设置对象没有任何效果,因为包含对象的变量只是对带有计数的内存中的数据的引用。如果$ a = new Object()然后$ b = $ a,则创建对该对象的新引用,同时保持其完整(未复制)。
如果要取消设置($ a),则只会取消设置对象的引用,而$ b仍会指向内存中的该对象。如果取消设置($ b),则会从内存中取消设置对象引用,因为没有任何内容指向它。
希望能让它更清晰......
祝你好运答案 2 :(得分:2)
请改用此行:
foreach ($products as &$product)
答案 3 :(得分:1)
试试这个:
// $id is the key, $product is the value
foreach ($products as $id => $product) {
if(!$product->active) {
unset($products[$id]);
}
}
答案 4 :(得分:1)
您无法取消设置变量本身。您需要使用foreach
语法,该语法还为您提供项目的密钥,并使用它来取消设置数组上的密钥:
foreach ($products as $key => $product) {
if(!$product->active) {
unset($products[$key]);
}
}
答案 5 :(得分:0)
或者,您可以使用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。