162

I iterate through an array of objects and want to delete one of the objects based on it's 'id' property, but my code doesn't work.

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

Any suggestions. Thanks.

ababa
  • 1,853
  • 4
  • 16
  • 14
  • 2
    possible duplicate of [How do you remove an array element in a foreach loop?](http://stackoverflow.com/questions/1949259/how-do-you-remove-an-array-element-in-a-foreach-loop) – 7hi4g0 Jan 29 '14 at 06:47

6 Answers6

268
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}
prodigitalson
  • 60,050
  • 10
  • 100
  • 114
  • 69
    Is it safe to remove an element of an array within a foreach loop of the same array? – Olivier Pons Aug 06 '12 at 11:00
  • 27
    @Oliver: usually it will generate unexpected behavior, but you can do it safely with foreach on php. Give a read here for a test: http://php.net/manual/en/control-structures.foreach.php#88578 – pangon Jan 26 '13 at 06:07
  • This is converting my array to object in CodeIgniter. Any suggestion? – Paritosh Oct 06 '16 at 18:14
  • 2
    @Paritosh I know you posted this a long time ago, but it's because PHP uses associative arrays. So you have an index that's deleted: and it's getting encoded to JSON as an Object. Makes sense, since an associative array is a "dictionary." Might help someone who's coming along. – Ryan O'Donnell Feb 27 '17 at 15:06
  • 1
    Do you really need to do the second for each ? can't you just query the desired 'id' property of the object? Why check all of the other props. – htafoya Dec 06 '17 at 23:06
  • 4
    @htafoya no you could just do `if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }` I think at the time i just copied and modified his code to show him how to `unset` properly. – prodigitalson Dec 21 '17 at 21:05
  • @pangon's reply could be misleading. His link shows `foreach` loop is unaffected by `unset`. If it is safe or not really depend on one's use case. – Binod Kalathil Jul 04 '20 at 14:29
5

Be careful with the main answer.

with

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

and calling the function

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

it returns

[2=>['id'=>3,'cat'=>'normal']

instead of

[0=>['id'=>3,'cat'=>'normal']

It is because unset does not re-index the array.

It reindexes. (if we need it)

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}
magallanes
  • 6,583
  • 4
  • 54
  • 55
2

It looks like your syntax for unset is invalid, and the lack of reindexing might cause trouble in the future. See: the section on PHP arrays.

The correct syntax is shown above. Also keep in mind array-values for reindexing, so you don't ever index something you previously deleted.

pablo.meier
  • 2,339
  • 4
  • 21
  • 29
1

This should do the trick.....

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}
Josh
  • 819
  • 1
  • 14
  • 30
-1

You can also use references on foreach values:

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}
air-dex
  • 4,130
  • 2
  • 25
  • 25
  • 10
    $element (used in and out of the foreach) is just a reference to each element in the array. unset($element) will just break reference, it does not destroy the referenced element from its array. – Nicholas Jan 20 '16 at 04:22
  • 3
    @Dev_NIX `$element = null` would NOT work, the length of `$array` remains the same, it would just contain nulls – Nico Westerdale Sep 06 '17 at 15:59
-5

I'm not much of a php programmer, but I can say that in C# you cannot modify an array while iterating through it. You may want to try using your foreach loop to identify the index of the element, or elements to remove, then delete the elements after the loop.

Corey Sunwold
  • 10,194
  • 6
  • 51
  • 55
  • 15
    While it is bad practice in most languages, arrays in PHP are basically associative arrays that can be iterated in order. Deleting an earlier element does not change the keys of elements that come after it. – Ignacio Vazquez-Abrams Feb 21 '10 at 03:02
  • 23
    Actually, it's allowed because the array that foreach uses internally is a copy of the original array. That way, modifying the original array is perfectly safe. – Juan Feb 21 '10 at 03:07
  • 70
    Actually, it's allowed because php is screwy as all hell. – Eric G Apr 06 '13 at 22:03