PHP bietet bei foreach-Schleifen keine Unterstützung für eine Veränderung von Arrays on-the-fly innerhalb der Schleife selbst. Es ist lediglich möglich, die veränderten Arrays nach der Schleife zu verwenden. Allerdings gibt es verschiedene Möglichkeiten, dieses Problem zu umgehen.

Schauen wir uns also zuerst die Ausgangslage an, die nur zur Ausgabe „123“ führt (erwünscht wäre „123new element“):

<?php
$array = array(1,2,3);
foreach ($array as $i => $a) {
	if ($i == 1) {
		$array[] = 'new element';
	}
	echo $a;
}

Umgehung mit for-Schleife

Die einfachste Möglichkeit, diese Funktionalität beim Hinzufügen von Werten zu erhalten, ist der Umweg über eine for-Schleife mit wiederholendem Aufruf von count(). Nachteil dieser Methode ist allerdings, dass man auf assoziative Indizes verzichten muss. Es funktioniert lediglich mit numerischen Indizes.

<?php
$array = array(1,2,3);
for ($i=0;$i<count($array);$i++) {
	if ($i == 1) {
		$array[] = 'new element';
	}
	echo $array[$i];
}

ArrayIterator

In den SPL-Klassen gibt es einen ArrayIterator, der sich dank der Implementierung von ArrayAccess genau wie ein Array verwenden lässt, jedoch eine on-the-fly-Veränderung der Werte innerhalb einer foreach-Schleife erlaubt. Dies liegt daran, dass Iterator ihre Werte jeweils einzeln mittels next() abrufen und mit valid() überprüfen, ob an der aktuellen Stelle noch ein Element ist.

<?php
$array = new ArrayIterator(array(1,2,3));
foreach ($array as $i => $a) {
	if ($i == 1) {
		$array[] = 'new element';
	}
	echo $a;
}

Der Benchmarking-Vergleich zwischen allen Methoden bei 10.000 Iterationen (ohne echo, mit Array-Deklaration) führt zu folgendem Ergebnis:

  • array + foreach: 0.0963s</li>
  • array + for: 0.387s</li>
  • ArrayIterator + foreach: 0.254s</li>

Man kann also ohne Bedenken von normalen Arrays auf einen ArrayIterator wechseln, wenn man ein Array innerhalb einer foreach-Schleife verändern muss, denn der ArrayIterator in Verbindung mit foreach ist immer noch schneller als eine for-Schleife mit ständiger Wiederholung von count().