foreach()/PHP 5.1.4: Das ist doch ein PHP-Bug, oder?

ManicMarble

Erfahrenes Mitglied
Hallo zusammen,
ich wundere mich gerade ein bischen:
PHP:
<?php
	$a = array(1, 2, 3, 4, 5, 6, 7);
	foreach ($a as &$val) echo $val;
	echo '<br>';
	foreach ($a as $val) echo $val;
?>
Erwarten würde ich als Ausgabe:
1234567
1234567​
PHP 5.1.4-pl6 macht aber das hier:
1234567
1234566​
Also: Zwei mal foreach() über das selbe Array, und immer mit der Zuweisung der Array-Elemente an die Variable $val, beim ersten Durchgang als Referenz, beim zweiten Durchgang als Wert. Beim zweiten foreach() wird das letzte Array-Element gleich dem vorletzten gesetzt. Wenn man beide Male $val verwendet oder beide male &$val, dann bleibt alles in Ordnung.

Bug oder Feature? :suspekt:
 
Keiner 'ne Idee? Irgendwie scheint doch da die automatische Typ-Umwandlung schiefzugehen, oder?

Ist übrigens auf meinem Heim-System (PHP 5.1.0 unter Windows) das gleiche. Wenn jemand von euch schon eine neuere PHP-Version als 5.1.4 einsetzt: Würde mich interessieren, ob das da auch noch so ist.

Mein Workaround: unset($val) vor dem zweiten foreach(), oder einfach immer mit Referenz arbeiten (&$val).
 
Das ist kein Bug sondern wohl eine Fehlinterpretation deinerseits wie Referenzen funktionieren. Denn in der ersten Schleife wird zuletzt die $val-Variable eine Referenz des letzten Array-Elements.
In der zweiten Schleife wird dann bei jedem Durchlauf der Wert des letzten Elements der $a-Variable geändert:
PHP:
$a = array(1, 2, 3, 4, 5, 6, 7); 
foreach($a as &$val) { }
$val = 'letztes Array-Element';
var_dump($a);

foreach($a as $val) {
	var_dump($a);
}
Aber du bist nicht der Einzige, der sich darüber Gedanken gemacht hat.
 
Hallo Gumbo,
danke für die Erklärung und danke für den Link! Hab' jetzt alles verstanden.
Ich teile jedenfalls die Meinung von kouber(at)php.net im PHP-Forum:
IMHO, foreach has to clear the variables used for key-value pairs, i.e.
to unset the reference before proceeding, just like it resets the array
pointer. Otherwise we have to put a big red note in the manual to always
unset variables after using the referential syntax or to use
$long_descriptive_names_for_references, which is a little unreasonable
in the current context.
Will sagen, das Verhalten mag streng genommen korrekt sein, es ist aber auf jeden Fall nicht das Verhalten, das 99% der PHP-Programmierer* erwarten würden, da PHP ansonsten auch nicht so "denkt". Man würde einfach erwarten, dass vor jedem foreach() alle für die Schleife verwendeten Variablen automatisch neu initialisiert werden. Das ist eine weiterere Ladung Wasser auf die Mühlen derer, die PHP für eine "hässliche Sprache" halten.
Sei's drum, ist nun mal so, ich werde mich auch damit abfinden müssen.

Nochmal Danke,
Martin

* Hier jetzt bitte zum 1001. mal den Flamewar "PHP wird nicht programmiert sondern gescriptet" starten...;)
 
Zurück