Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: Get Object From Collection By Attribute

Tags:

php

mysql

laravel

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.  :( 
like image 984
Leng Avatar asked Jan 05 '14 07:01

Leng


1 Answers

You can use filter, 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.

You don't need the filter anymore (or maybe ever, I don't know this is almost 4 years old). You can just use first:

$desired_object = $food->first(function($item) {     return $item->id == 24; }); 
like image 163
kalley Avatar answered Sep 20 '22 19:09

kalley