sofas rematime pedido colgantes php mysql laravel

php - rematime - colgantes a pedido



Laravel: Obtener Object From Collection por atributo (8)

En Laravel, si realizo una consulta:

$foods = Food::where(...)->get();

... entonces $foods es un objeto Illuminate Collection of Food model. (Esencialmente una matriz de modelos).

Sin embargo, las claves de esta matriz son simplemente:

[0, 1, 2, 3, ...]

... así que si quiero alterar, por ejemplo, el objeto Food con una id de 24, no puedo hacer esto:

$desired_object = $foods->get(24); $desired_object->color = ''Green''; $desired_object->save();

... porque esto simplemente alterará el elemento 25 en la matriz, no el elemento con una id de 24.

¿Cómo obtengo un elemento único (o múltiple) de una colección por CUALQUIER atributo / columna (como, pero no limitado a, id / color / age / etc.)?

Por supuesto, puedo hacer esto:

foreach ($foods as $food) { if ($food->id == 24) { $desired_object = $food; break; } } $desired_object->color = ''Green''; $desired_object->save();

... pero, eso es asqueroso.

Y, por supuesto, puedo hacer esto:

$desired_object = Food::find(24); $desired_object->color = ''Green''; $desired_object->save();

... pero eso es aún más asqueroso , porque realiza una consulta innecesaria adicional cuando ya tengo el objeto deseado en la colección $foods .

Gracias de antemano por cualquier orientación.

EDITAR:

Para que quede claro, puede llamar a ->find() en una colección Illuminate sin generar otra consulta, pero solo acepta una ID principal. Por ejemplo:

$foods = Food::all(); $desired_food = $foods->find(21); // Grab the food with an ID of 21

Sin embargo, todavía no hay una forma limpia (sin bucles, sin consultas) de agarrar un elemento (s) por un atributo de una Colección, como este:

$foods = Food::all(); $green_foods = $foods->where(''color'', ''green''); // This won''t work. :(


Como la pregunta anterior cuando usa la cláusula where, también necesita usar el método get or first para obtener el resultado.

/** *Get all food * */ $foods = Food::all(); /** *Get green food * */ $green_foods = Food::where(''color'', ''green'')->get();


Como no es necesario que bucle toda la colección, creo que es mejor tener la función auxiliar como este

/** * 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; }


Debo señalar que hay un error pequeño pero absolutamente CRÍTICO en la respuesta de Kalley. Luché con esto durante varias horas antes de darme cuenta:

Dentro de la función, lo que estás devolviendo es una comparación, y por lo tanto, algo así sería más correcto:

$desired_object = $food->filter(function($item) { return ($item->id **==** 24); })->first();


Laravel proporciona un método llamado keyBy que permite establecer claves por clave dada en el modelo.

$collection = $collection->keyBy(''id'');

devolverá la colección pero con las claves siendo los valores del atributo id de cualquier modelo.

Entonces puedes decir:

$desired_food = $foods->get(21); // Grab the food with an ID of 21

y tomará el elemento correcto sin el desorden de usar una función de filtro.


Puede usar el filter , así:

$desired_object = $food->filter(function($item) { return $item->id == 24; })->first();

filter también devolverá una Collection , pero como sabes que solo habrá una, puedes llamar first a esa Collection .

Ya no necesita el filtro (o tal vez nunca, no sé si tiene casi 4 años). Puedes usar first :

$desired_object = $food->first(function($item) { return $item->id == 24; });


Sé que esta pregunta se hizo originalmente antes de que se lanzara Laravel 5.0, pero a partir de Laravel 5.0, Collections admite el método where() para este fin.

Para Laravel 5.0, 5.1 y 5.2, el método where() en la Collection solo hará una comparación igual. Además, hace una comparación igual estricta ( === ) por defecto. Para hacer una comparación suelta ( == ), puede pasar false como el tercer parámetro o usar el método whereLoose() .

A partir de Laravel 5.3, el método where() se expandió para funcionar más como el método where() para el generador de consultas, que acepta un operador como el segundo parámetro. También al igual que el generador de consultas, el operador establecerá de manera predeterminada una comparación igual si no se proporciona ninguna. La comparación predeterminada también cambió de estricta por defecto a suelta por defecto. Entonces, si desea una comparación estricta, puede usar whereStrict() , o simplemente usar === como el operador de where() .

Por lo tanto, a partir de Laravel 5.0, el último ejemplo de código en la pregunta funcionará exactamente como se esperaba:

$foods = Food::all(); $green_foods = $foods->where(''color'', ''green''); // This will work. :) // This will only work in Laravel 5.3+ $cheap_foods = $foods->where(''price'', ''<'', 5); // Assuming "quantity" is an integer... // This will not match any records in 5.0, 5.1, 5.2 due to the default strict comparison. // This will match records just fine in 5.3+ due to the default loose comparison. $dozen_foods = $foods->where(''quantity'', ''12'');



Utilice los métodos de recopilación incorporados que contienen y encuentran , que buscarán por identificadores primarios (en lugar de claves de matriz). Ejemplo:

if ($model->collection->contains($primaryId)) { var_dump($model->collection->find($primaryId); }

contains () realmente solo llama a find () y busca nulo, por lo que puedes acortarlo a:

if ($myModel = $model->collection->find($primaryId)) { var_dump($myModel); }