Wenn ich in Laravel eine Abfrage durchführe:
$foods = Food::where(...)->get();
... dann $foods
ist eine Illuminate Collection von Food
Modellobjekten. (Im Wesentlichen eine Reihe von Modellen.)
Die Schlüssel dieses Arrays sind jedoch einfach:
[0, 1, 2, 3, ...]
... Wenn ich also beispielsweise das Food
Objekt mit einer id
von 24 ändern möchte , kann ich dies nicht tun:
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
... weil dies lediglich das 25. Element im Array ändert, nicht das Element mit einem id
von 24.
Wie erhalte ich ein einzelnes (oder mehrere) Element (e) aus einer Sammlung nach JEDEM Attribut / jeder Spalte (z. B. ID / Farbe / Alter / usw.), ohne darauf beschränkt zu sein?
Natürlich kann ich das tun:
foreach ($foods as $food) {
if ($food->id == 24) {
$desired_object = $food;
break;
}
}
$desired_object->color = 'Green';
$desired_object->save();
... aber das ist nur eklig.
Und natürlich kann ich das tun:
$desired_object = Food::find(24);
$desired_object->color = 'Green';
$desired_object->save();
... aber das ist noch schlimmer , weil es eine zusätzliche unnötige Abfrage ausführt, wenn ich bereits das gewünschte Objekt in der $foods
Sammlung habe.
Vielen Dank im Voraus für jede Anleitung.
BEARBEITEN:
Um klar zu sein, können Sie eine Illuminate Collection aufrufen, ohne eine weitere Abfrage zu erzeugen->find()
, aber es wird nur eine primäre ID akzeptiert. Zum Beispiel:
$foods = Food::all();
$desired_food = $foods->find(21); // Grab the food with an ID of 21
Es gibt jedoch immer noch keine saubere (nicht schleifenförmige, nicht abfragende) Möglichkeit, ein oder mehrere Elemente anhand eines Attributs aus einer Sammlung wie folgt zu erfassen:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work. :(
filter()->first()
man kann einfach anrufenfirst(function(...))
collect([1, 2, 3, 4])->first(function ($value, $key) { return $value == 2; });
$desired_object = $food->where('id', 24)->first();
Laravel bietet eine Methode namens
keyBy
, mit der Schlüssel anhand eines bestimmten Schlüssels im Modell festgelegt werden können.$collection = $collection->keyBy('id');
gibt die Sammlung zurück, wobei Schlüssel die Werte des
id
Attributs eines beliebigen Modells sind.Dann können Sie sagen:
$desired_food = $foods->get(21); // Grab the food with an ID of 21
und es wird das richtige Element erfassen, ohne dass eine Filterfunktion verwendet werden muss.
quelle
$exceptions->keyBy(function ($exception) { return $exception->category_id . ' ' . $exception->manufacturer_id;
und->get($category->id . ' ' . $manufacturer->id)
danach verwenden können!keyBy
neue Sammlung von dem zurückgegeben wird, woran ich mich erinnere. Sie sind sich jedoch nicht sicher, ob Sie dies überprüfen könnenIlluminate/Support/Collection
. (Ich arbeite seit einiger Zeit nicht mehr in Laravel, damit mich jemand korrigieren kann.)Ab Laravel 5.5 können Sie firstWhere () verwenden.
In Ihrem Fall:
quelle
Da ich nicht die gesamte Sammlung durchlaufen muss, ist es meiner Meinung nach besser, eine solche Hilfsfunktion zu haben
quelle
Verwenden Sie die integrierten Auflistungsmethoden enthalten und suchen , die nach primären IDs (anstelle von Array-Schlüsseln) suchen. Beispiel:
enthält () ruft eigentlich nur find () auf und sucht nach null, so dass Sie es auf Folgendes verkürzen können:
quelle
Ich weiß, dass diese Frage ursprünglich gestellt wurde, bevor Laravel 5.0 veröffentlicht wurde, aber ab Laravel 5.0 unterstützen Sammlungen die
where()
Methode für diesen Zweck.Für Laravel 5.0, 5.1 und 5.2 führt die
where()
Methode auf demCollection
nur einen Vergleich durch. Außerdem===
wird standardmäßig ein strikter Vergleich ( ) durchgeführt. Um einen losen Vergleich (==
) durchzuführen, können Sie entwederfalse
als dritten Parameter übergeben oder diewhereLoose()
Methode verwenden.Ab Laravel 5.3 wurde die
where()
Methode so erweitert, dass sie eher derwhere()
Methode für den Abfrage-Generator ähnelt, der einen Operator als zweiten Parameter akzeptiert. Ebenso wie der Abfrage-Generator verwendet der Operator standardmäßig einen Gleichheitsvergleich, wenn keiner angegeben wird. Der Standardvergleich wurde ebenfalls standardmäßig von streng auf lose umgestellt. Wenn Sie also einen strengen Vergleich wünschen, können SiewhereStrict()
oder nur===
als Operator für verwendenwhere()
.Ab Laravel 5.0 funktioniert das letzte Codebeispiel in der Frage daher genau wie beabsichtigt:
quelle
Ich muss darauf hinweisen, dass Kalleys Antwort einen kleinen, aber absolut kritischen Fehler enthält. Ich hatte mehrere Stunden damit zu kämpfen, bevor mir klar wurde:
Innerhalb der Funktion geben Sie einen Vergleich zurück, und daher wäre so etwas korrekter:
quelle
foreach()
Leistung nicht von meinem Beispiel unterscheidet , da sie nur die gleiche Art von Schleifeforeach()
ausführt. Tatsächlich ist mein Beispiel leistungsfähiger, da es beim Finden des richtigen Modells unterbrochen wird. Auch ...{Collection}->find(24)
wird nach Primärschlüssel greifen, was es hier zur besten Option macht. Der vorgeschlagene Filter Kalley ist tatsächlich identisch mit$desired_object = $foods->find(24);
.**==**
Bediener noch nie gesehen . Was macht er?Elegante Lösung, um einen Wert zu finden ( http://betamode.de/2013/10/17/laravel-4-eloquent-check-if-there-is-a-model-with-certain-key-value-pair-in -a-collection / ) kann angepasst werden:
quelle
Als obige Frage, wenn Sie die where-Klausel verwenden, müssen Sie auch die Methode get Or first verwenden, um das Ergebnis zu erhalten.
quelle