Laravel: Get Object From Collection By Attribute
Laravel: Get Object From Collection By Attribute
In Laravel, if I perform a query:
$foods = Food::where(...)->get();
...then $foods
is an Illuminate Collection of Food
model objects. (Essentially an array of models.)
However, the keys of this array are simply:
[0, 1, 2, 3, ...]
...so if I want to alter, say, the Food
object with an id
of 24, I can't do this:
$desired_object = $foods->get(24); $desired_object->color = 'Green'; $desired_object->save();
...because this will merely alter the 25th element in the array, not the element with an id
of 24.
How do I get a single (or multiple) element(s) from a collection by ANY attribute/column (such as, but not limited to, id / color / age / etc.)?
Of course, I can do this:
foreach ($foods as $food) { if ($food->id == 24) { $desired_object = $food; break; } } $desired_object->color = 'Green'; $desired_object->save();
...but, that's just gross.
And, of course, I can do this:
$desired_object = Food::find(24); $desired_object->color = 'Green'; $desired_object->save();
...but that's even more gross, because it performs an additional unnecessary query when I already have the desired object in the $foods
collection.
Thanks in advance for any guidance.
EDIT:
To be clear, you can call ->find()
on an Illuminate Collection without spawning another query, but it only accepts a primary ID. For instance:
$foods = Food::all(); $desired_food = $foods->find(21); // Grab the food with an ID of 21
However, there is still no clean (non-looping, non-querying) way to grab an element(s) by an attribute from a Collection, like this:
$foods = Food::all(); $green_foods = $foods->where('color', 'green'); // This won't work. :(
Answer by kalley for Laravel: Get Object From Collection By Attribute
You can use filter
(under Support), like so:
$desired_object = $food->filter(function($item) { return $item->id == 24; })->first();
filter
will also return a Collection
, but since you know there will be only one, you can call first
on that Collection
.
Answer by squaretastic for Laravel: Get Object From Collection By Attribute
I have to point out that there is a small but absolutely CRITICAL error in kalley's answer. I struggled with this for several hours before realizing:
Inside the function, what you are returning is a comparison, and thus something like this would be more correct:
$desired_object = $food->filter(function($item) { return ($item->id **==** 24); })->first();
Answer by Rohith Raveendran for Laravel: Get Object From Collection By Attribute
Since I don't need to loop entire collection, I think it is better to have helper function like this
/** * Check if there is a item in a collection by given key and value * @param Illuminate\Support\Collection $collection collection in which search is to be made * @param string $key name of key to be checked * @param string $value value of key to be checkied * @return boolean|object false if not found, object if it is found */ function findInCollection(Illuminate\Support\Collection $collection, $key, $value) { foreach ($collection as $item) { if (isset($item->$key) && $item->$key == $value) { return $item; } } return FALSE; }
Answer by softfrog for Laravel: Get Object From Collection By Attribute
Elegant solution for finding a value (http://betamode.de/2013/10/17/laravel-4-eloquent-check-if-there-is-a-model-with-certain-key-value-pair-in-a-collection/) can be adapted:
$desired_object_key = $food->array_search(24, $food->lists('id')); if ($desired_object_key !== false) { $desired_object = $food[$desired_object_key]; }
Answer by Ziad Hilal for Laravel: Get Object From Collection By Attribute
Use the built in collection methods contain and find, which will search by primary ids (instead of array keys). Example:
if ($model->collection->contains($primaryId)) { var_dump($model->collection->find($primaryId); }
contains() actually just calls find() and checks for null, so you could shorten it down to:
if ($myModel = $model->collection->find($primaryId)) { var_dump($myModel); }
Answer by Maksym Cierzniak for Laravel: Get Object From Collection By Attribute
Laravel provides a method called keyBy
which allows to set keys by given key in model.
$collection = $collection->keyBy('id');
will return the collection but with keys being the values of id
attribute from any model.
Then you can say:
$desired_food = $foods->get(21); // Grab the food with an ID of 21
and it will grab the correct item without the mess of using a filter function.
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment