php Problem mit Schleife über ein array zweimal mit foreach und Wert übergeben nach Verweis
Muss ich eine Schleife durch ein array zweimal - einmal, um ändern Sie Ihre Werte, und einmal, um die Anzeige Ihrer Inhalte in html. Ich bin leider läuft in Schwierigkeiten. Erstellt habe ich ein test-Szenario zur Verdeutlichung des Problems.
$cases = array(
array('caseStyle' => 'case style 1', 'caseNum' => 'case01'),
array('caseStyle' => 'case style 2', 'caseNum' => 'case02'),
array('caseStyle' => 'case style 3', 'caseNum' => 'case03'),
array('caseStyle' => 'case style 4', 'caseNum' => 'case04'),
array('caseStyle' => 'case style 5', 'caseNum' => 'case05'),
array('caseStyle' => 'case style 6', 'caseNum' => 'case06')
);
foreach ($cases as $k => &$v) {
$v['caseNum'] = ucwords($v['caseNum']);
}
foreach ($cases as $k => $v) {
echo $v['caseNum'] . ' - ' . $v['caseStyle'] . '<br/>';
}
Dieser Ausgänge:
Case01 - case style 1
Case02 - case style 2
Case03 - case style 3
Case04 - case style 4
Case05 - case style 5
Case05 - case style 5
Hinweis: die Werte für den letzten Punkt sind falsch.
Wenn während der zweiten iteration ich verwenden
foreach($cases as $k => $d)
statt foreach($cases as $k => $v)
oder wenn ich unset $v
vor der zweiten iteration (unset($v))
geht alles in Ordnung. Das ist faszinierend. Was bin ich?
- Warum müssen Sie dies tun, in zwei loops? Warum nicht beides das erste mal durch?
- Im tatsächlichen code das array ist eine sperrige bad-ass-array von arrays mit den Zeilen zurückgegeben, die von der db. In der ersten iteration ist I-Bereinigung, fügen Sie defaults für fehlende Werte, Formate ändern, wo nötig, und fügen Sie zusätzliche Felder gezogen aus anderen Tabellen zu. Die zweite iteration ist, wenn ich Male die html-Seite mit den Werten aus dem array (das ist der legacy-code - html-und php alles in einer Datei, keine Vorlagen 🙁 )
- Das noch nicht bedeutet Sie können nicht tun es alle auf einmal. Auch wenn Sie müssen, verwenden Sie die Werte aus dem array, bevor er Sie anzeigt, können Sie den Puffer für die Ausgabe in eine variable und echo heraus, die variable, wenn nötig. Wenn sich die Komplexität, die das problem verursacht, entfernen Sie die Komplexität 😉
- Ihr Punkt ist gut genommen. Für diese Angelegenheit, einfach mit einer anderen variable in der foreach-oder lösche $v vor der zweiten iteration ist die Lösung des Problems. Allerdings wäre das ein blind-Lösung. Ich brauche, um zu verstehen, was hier geschieht.
- Ich habe eine Gründliche Erklärung, was in einer Antwort weiter unten.
- anstelle von $v in der zweiten Schleife etwas anderes verwenden
- Die Variable $v aus der ersten Schleife zugewiesen, in der zweiten Schleife.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beim ausführen einer
foreach
- Schleife werden die Variablen in der()
bestehen, nachdem die Schleife fertig ist. Das bedeutet, dass nach der ersten Schleife abgeschlossen ist, können Sievar_dump($v)
und Holen Sie sich die Werte enthalten waren es nach der letzten iteration der ersten Schleife. Dies ist der Fall, ob es eine Referenz (&$v
) oder eine normale variable ($v
).Jedoch, wenn es ein Verweis in der ersten Runde, es bleibt ein Verweis, es sei denn, es ist ausgeschaltet. Das bedeutet, dass, wenn Sie geben Sie die zweite Schleife, Sie überschreiben die Referenz mit dem Wert des array-Elements, dem Sie gerade betrachten.
Erinnern, was
foreach($cases as $k => $v)
wirklich bedeutet, ist "der Schlüssel für dieses element in $Fällen und weisen, dass $k, und der Wert für dieses element, und weisen Sie $v)". Da $v noch einen Verweis auf das Letzte element im array, sondern als Einstellung, die den Wert einer neuen variable $v, Sie sind eigentlich die Aktualisierung des Werts, wobei $v weist schon.Was das bedeutet, ist, wenn wir vereinfachen die $cases einfach
['a', 'b', 'c', 'd']
, nach dem ersten mal durch die zweite foreach $Fällen ist jetzt['a', 'b', 'c', 'a']
da hast du zugewiesen, das element in $Fällen $v Punkte zu - der Letzte - haben den gleichen Wert wie der erste. Das zweite mal durch, es ist['a', 'b', 'c', 'b']
. Das Dritte mal durch, es ist['a', 'b', 'c', 'c']
. Dann, das Letzte mal durch, du bist die Zuordnung zu sich selbst, und in dieser Zeit hält es das Wert'c'
.Dies ist wirklich nur ein Fall von php arbeiten, wie erwartet. Die Lösung ist
unset($v)
sobald die erste Schleife wird beendet, um sicherzustellen, dass das nächste mal, wenn Sie $v wenn Sie eine neue variable, anstatt eine vorhandene Referenz.Um dies in Aktion zu sehen:
Den Kopf über http://phpfiddle.org/ und fügen Sie den folgenden code, und starten Sie es; Sie sehen in der Ausgabe, die
$v
aufrechterhalten wird, nachdem die erste Schleife abgeschlossen ist, und dass der Wert von$cases[5]
ändert sich jedes mal durch die zweite Schleife.Versuchen Sie dies:
Hier ist eine ähnliche Frage, die hat ein paar gute Erklärungen dafür, warum dieses Problem Auftritt.
PHP übergabe per Referenz in foreach
Lassen Sie mich wissen, ist dies Ihre Lösung: