Vielleicht keine spezifische Frage zu Eloquent-Sammlungen, aber es hat mich einfach getroffen, als ich mit ihnen gearbeitet habe. Nehmen wir einfach an, wir haben a $collection Objekt, das eine Instanz von ist Illuminate\Support\Collection.
Nun, wenn wir darüber iterieren wollen, was sind die Vor- und Nachteile der Verwendung von each() mit einem Verschluss im Vergleich zu einem regulären foreach. Sind da welche?
foreach ($collection as $item) {
// Some code
}
gegen
$collection->each(function ($item) {
// Some code
});
Wenn Sie sie noch nicht gesehen haben, möchten Sie vielleicht die Kommentare zur akzeptierten Antwort lesen. Es ist falsch, und ich schlage vor, Sie akzeptieren es nicht.
– Mark Amery
7. Juni 2015 um 0:49 Uhr
da ich das gerade in 5.1 ausprobiere, scheint die each()-Methode völlig nutzlos zu sein, da sie sowieso $item nicht ändert.
– SS
1. Oktober 2016 um 10:12 Uhr
Hast du ein return $item; Am Ende?
– Niklas Modess
2. Oktober 2016 um 13:14 Uhr
Säge
EIN foreach -Anweisung sollte als eine Art Methode verwendet werden, um durch eine Sammlung zu blättern und eine Art Logik darauf anzuwenden. Wenn der Inhalt andere Dinge im Programm beeinflusst, verwenden Sie diese Schleife.
Das .each Methode verwendet array_map um durch jedes der Objekte in der Sammlung zu blättern und einen Abschluss für jedes durchzuführen. Es gibt dann das resultierende Array zurück. Das ist der Schlüssel! .each sollte verwendet werden, wenn Sie die Sammlung auf irgendeine Weise ändern möchten. Vielleicht handelt es sich um eine Reihe von Autos und Sie möchten das Modell in Groß- oder Kleinbuchstaben schreiben. Sie würden nur eine Schließung an die übergeben .each Methode, die das Objekt übernimmt und aufruft strtoupper() auf dem Modell jedes Autoobjekts. Anschließend wird die Sammlung mit den vorgenommenen Änderungen zurückgegeben.
Die Moral der Geschichte ist: Verwenden Sie die .each Methode, um jedes Element im Array auf irgendeine Weise zu ändern; benutze die foreach Schleife, um jedes Objekt zu verwenden, um einen anderen Teil des Programms zu beeinflussen (unter Verwendung einer logischen Anweisung).
UPDATE (7. Juni 2015)
Wie so Eloquently (sehen Sie, was ich dort getan habe?) Unten erwähnt, ist die obige Antwort etwas daneben. Das .each Methode verwenden array_map nie wirklich die Ausgabe von verwendet array_map Anruf. Also, das neue Array erstellt von array_map würde nicht auf die gespeichert werden Collection. Um es zu ändern, verwenden Sie besser die .map Methode, die auch auf a existiert Collection Objekt.
Verwendung einer foreach Anweisung, über jeden von ihnen zu iterieren, ist etwas sinnvoller, da Sie nicht auf Variablen außerhalb der Closure zugreifen können, es sei denn, Sie stellen sicher, dass Sie a verwenden use Aussage, die mir peinlich erscheint.
Die Implementierung, wenn die obige Antwort ursprünglich geschrieben wurde, kann sein hier gefunden.
.each in Laravel 5.1
Das neue .each worüber sie unten sprechen, wird nicht mehr verwendet array_map. Es iteriert einfach durch jedes Element in der Sammlung und ruft das übergebene auf $callback, und übergibt ihm das Element und seinen Schlüssel im Array. Funktionell scheint es gleich zu funktionieren. Ich glaube, mit a foreach Schleife würde beim Lesen des Codes mehr Sinn machen. Ich sehe jedoch die Vorteile der Verwendung .each weil es Ihnen erlaubt, Methoden miteinander zu verketten, wenn Ihnen das gefällt. Außerdem können Sie vom Rückruf false zurückgeben, um die Schleife vorzeitig zu verlassen, wenn Ihre Geschäftslogik dies erfordert.
Weitere Informationen zur neuen Implementierung finden Sie unter der Quellcode.
Das alles machte Sinn für mich und dann habe ich verwendet .each auf eine Sammlung von Arrays, um jedes Array als Objekt umzuwandeln. Ich konnte die Variable, die ich in der Callback-Funktion zurückgab, ausgeben, es war ein Objekt. aber danach … immer noch ein Array. Ich mache mir Sorgen, dass ich etwas falsch verstehe
– Dämon
9. August 2014 um 18:03 Uhr
Es hört sich so an, als würden Sie das Objekt nicht zurückgeben. Sie müssen sicherstellen, dass Sie das gecastete Objekt von der Callback-Funktion zurückgeben, damit es in das Array und nicht in das gecastete Array ausgegeben wird.
– Seesäge
9. August 2014 um 22:24 Uhr
Diese Antwort ist falsch und basiert auf einem Missverständnis des Codes. Die Tatsache, dass .each array_map() verwendet, ist irrelevant, das ist nur ein Implementierungsdetail. Tatsächlich ist der Laravel-Code für .each() gibt nicht einmal den Rückgabewert von zurück array_map(), wird einfach ignoriert. Beide .each() und foreach sind ebenso nützlich (oder nicht nützlich!) zum Ändern der Werte. Siehe meine Antwort für Details.
– bestell
6. Juni 2015 um 18:51 Uhr
Diese Antwort ist schrecklich falsch. PHP-Objekte sind änderbar, und wann immer Sie sie als Variablen übergeben, übergeben Sie tatsächlich Referenzen auf sie. daher können Sie ein vorhandenes Objekt mutieren aus dem Körper von a foreachaus einem array_map Rückruf, oder tatsächlich von jedem Code überhaupt. Das ist kein Unterschied zwischen foreach und array_map. Sie schlagen dies vor, indem Sie etwas aus dem Rückruf zurückgeben, an den Sie übergeben wurden $collection->each() Sie können die Sammlung ändern. Das stimmt auch nicht. Das each zum Aufrufen verwendete Methode array_map (vor April 2015), aber es hat den Rückgabewert nicht verwendet.
– Mark Amery
7. Juni 2015 um 0:36 Uhr
Danke für das Update @searsaw! Es wirkt wie ein Zauber!
– Stefan
11. Juni 2015 um 23:32 Uhr
ord
Es gibt viele verwirrende Fehlinformationen in den vorhandenen Antworten.
Die kurze Antwort
Die kurze Antwort lautet: Es gibt keinen großen Unterschied zwischen der Verwendung .each() vs. foreach um über eine Laravel-Sammlung zu iterieren. Beide Techniken erzielen das gleiche Ergebnis.
Was ist mit dem Ändern von Artikeln?
Ob Sie Elemente ändern oder nicht, ist für die Verwendung irrelevant .each() vs. foreach. Beide erlauben es Ihnen (und nicht!), Gegenstände in der Sammlung zu modifizieren, je nachdem, um welche Art von Gegenständen es sich handelt.
Ändern von Elementen, wenn die Sammlung Objekte enthält: Wenn die Sammlung eine Reihe von PHP-Objekten ist (z. B. eine Eloquent-Sammlung), auch nicht .each() oder foreach ermöglichen es Ihnen, Eigenschaften der Objekte zu ändern (wie z $item->name="foo"). Das liegt einfach daran, dass sich PHP-Objekte immer wie Referenzen verhalten. Wenn Sie versuchen, das gesamte Objekt durch ein anderes Objekt zu ersetzen (ein weniger häufiges Szenario), verwenden Sie .map() stattdessen.
Ändern von Elementen, wenn die Sammlung keine Objekte enthält: Dies ist weniger üblich, aber wenn Ihre Sammlung Nicht-Objekte wie Zeichenfolgen enthält, .each() gibt Ihnen keine Möglichkeit, die Werte der Sammlungselemente zu ändern. (Der Rückgabewert der Closure wird ignoriert.) Use .map() stattdessen.
Also … welches soll ich verwenden?
Falls Sie sich über die Leistung wundern, ich habe mehrere Tests mit großen Sammlungen von Eloquent-Elementen und einer Sammlung von Saiten durchgeführt. In beiden Fällen mit foreach war schneller als .each(). Aber wir reden hier von Mikrosekunden. In den meisten realen Szenarien wäre der Geschwindigkeitsunterschied im Vergleich zur Zeit, die für den Zugriff auf die Datenbank usw. benötigt wird, nicht signifikant.
Dabei kommt es vor allem auf Ihre persönlichen Vorlieben an. Verwenden .each() ist schön, weil Sie mehrere Operationen miteinander verketten können (z .where(...).each(...)). Ich neige dazu, beide in meinem eigenen Code zu verwenden, je nachdem, was für die jeweilige Situation am saubersten erscheint.
was ist für dich kein unterschied? Ein einfacher Test ergab ~ 1 Sekunde für 10000 Iterationen über 1000 Elemente mit ->jedem und ~ 0,4 für dieselbe Sammlung. das ist 2/5. Wenn irgendetwas objektiv ist, dann sind es diese nackten Zahlen – nicht die Vorliebe für die Verkettung von Anrufen.
– iRaS
24. Oktober 2020 um 10:53 Uhr
Im Gegensatz zu dem, was die beiden anderen Antworten sagen, Collection::each() tut nicht Ändern Sie technisch gesehen die Werte der Gegenstände in der Sammlung. Es nutzt array_map()aber das Ergebnis dieses Aufrufs wird nicht gespeichert.
Wenn Sie jedes Element in einer Sammlung ändern möchten (z. B. um sie in einem Kommentar zur derzeit akzeptierten Antwort in Objekte als Damon umzuwandeln), sollten Sie verwenden Collection::map(). Dadurch wird eine neue Sammlung erstellt, die auf dem Ergebnis des zugrunde liegenden Aufrufs von basiert array_map().
Ein paar Tage, nachdem Sie diese Antwort geschrieben haben, Illuminate\Support\Collection::each()nutzt gar nicht array_map mehr.
– Mark Amery
7. Juni 2015 um 0:28 Uhr
Nik K
Es ist vorteilhafter, letzteres zu verwenden: each().
Sie können Bedingungen verketten und klareren, aussagekräftigeren Code schreiben, z.
$example->each()->map()->filter();
Dies bringt Sie der deklarativen Programmierung näher, bei der Sie dem Computer sagen, was er erreichen soll, anstatt wie er es erreichen soll.
->each() ist der gleich wie foreach(...)aber schlimmer.
Der Hauptunterschied ist hier Variabler Umfang. Im klassischforeach Sie können Variablen, die vor deklariert sind, problemlos verwenden foreach. Wenn Sie es mit einer Schließung zu tun haben, müssen Sie dies tun erben von Variablen aus dem übergeordneten Gültigkeitsbereich mit use. Diese Funktion ist verwirrend, denn wenn Sie sie verwenden, wird Ihre Funktion bereichsabhängig …
Du kannst ketten ->each() mit anderen Funktionen, aber da es die Werte in der Sammlung nicht ändert, hat es einen sehr begrenzten Anwendungsfall. Und weil es “selten zu verwenden” ist, ist es für Entwickler nicht immer leicht erkennbar, wenn sie Ihren Code lesen.
Nicht viele Leute werden Ihren Code lesen, schätzen Sie diejenigen, die es tun.
Shannon
Mit dem Konstrukt foreach() können Sie den Wert des Array-Elements, über das iteriert wird, nicht ändern, es sei denn, Sie übergeben das Array als Referenz.
foreach ($array as &$value) $value *= $value;
Die eloquente Methode each() umschließt die PHP-Funktion array_map(), was dies ermöglicht.
Wie die vorherige Antwort besagt, sollten Sie foreach() verwenden, wenn Sie eine andere Motivation haben. Dies liegt daran, dass die Leistung von foreach() viel besser ist als die von array_map().
Wenn Sie sie noch nicht gesehen haben, möchten Sie vielleicht die Kommentare zur akzeptierten Antwort lesen. Es ist falsch, und ich schlage vor, Sie akzeptieren es nicht.
– Mark Amery
7. Juni 2015 um 0:49 Uhr
da ich das gerade in 5.1 ausprobiere, scheint die each()-Methode völlig nutzlos zu sein, da sie sowieso $item nicht ändert.
– SS
1. Oktober 2016 um 10:12 Uhr
Hast du ein
return $item;
Am Ende?– Niklas Modess
2. Oktober 2016 um 13:14 Uhr