4

Why can't I unset a variable in a foreach loop?

<?php

$array = array(a,s,d,f,g,h,j,k,l);

foreach($array as $i => $a){
 unset($array[1]);
 echo $a . "\n";
}

print_r($array);

In the code, the variable is in scope within the foreach loop, but outside the loop it's unset. Is it possible to unset it within the loop?

Ricardo Altamirano
  • 14,650
  • 21
  • 72
  • 105
Daniel Pairen
  • 187
  • 1
  • 2
  • 6
  • 7
    In pretty much every programming language it's a bad idea to modify a collection whilst iterating over it. – Anthony Grist Jun 28 '12 at 12:52
  • 1
    As I recall you need to set the array by ref.: `foreach(&$array as $i => $a){` – Brett Zamir Jun 28 '12 at 12:52
  • possible duplicate of [Unset an array element inside a foreach loop](http://stackoverflow.com/questions/3054886/unset-an-array-element-inside-a-foreach-loop) – Michael Berkowski Jun 28 '12 at 12:53
  • possible duplicate of [Unset array element inside a foreach loop](http://stackoverflow.com/questions/2852344/unset-array-element-inside-a-foreach-loop) – KV Prajapati Jun 28 '12 at 12:53
  • [Accepted answer here is a proper explanation of what's actually happening and why](http://stackoverflow.com/questions/10057671/how-foreach-actually-works). In a nutshell, `foreach` is [Copy-on-Write](http://en.wikipedia.org/wiki/Copy-on-write). – DaveRandom Jun 28 '12 at 12:55

3 Answers3

8

You need to pass the array by reference, like so:

foreach($array as $i => &$a){

Note the added &. This is also stated in the manual for foreach:

In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

This now produces:

a
d
f
g
h
j
k
l
Array
(
    [0] => a
    [2] => d
    [3] => f
    [4] => g
    [5] => h
    [6] => j
    [7] => k
    [8] => l
)
nickb
  • 59,313
  • 13
  • 108
  • 143
4

The foreach executes on a copy of the array, not a reference, to make it easier to deal with more drastic changes in the array (such as yours) during execution.

Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75
2

foreach iterates over the array and assigns the key to $i and the value to $a before accessing the code block inside the loop. The array is actually "copied" by the function before being iterated over, so any changes to the original array does not affect the progression of the loop.

You can also pass the $array by reference into the foreach using $i => &$a instead of by value which will allow the mutation of the array.

Another option would be to work directly on the array, and you would see something different:

for($x=0;$x<count($array);$x++){
    unset($array[1]);
    // for $x=1 this would result in an error as key does not exist now
    echo $array[$x];
}

print_r($array);

Of course, this assumes that your array is numerically and sequentially keyed.

Paul Bain
  • 4,364
  • 1
  • 16
  • 30