Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent - Updating all models in a collection

I want to set a certain attribute in all the models of a collection.

in plain SQL:

UPDATE table SET att = 'foo' WHERE id in (1,2,3)

the code i have:

$models = MyModel::findMany([1,2,3]);
$models->update(['att'=>'foo']);

taken from here

but doesn't work. I'm getting

Call to undefined method Illuminate\Database\Eloquent\Collection::update()

the only way i have found it's building a query with the query builder but i'd rather avoid that.

like image 553
Jarry Avatar asked Feb 05 '15 17:02

Jarry


People also ask

What does all () do in Laravel?

all() is a static method on the Eloquent\Model . All it does is create a new query object and call get() on it. With all() , you cannot modify the query performed at all (except you can choose the columns to select by passing them as parameters). get() is a method on the Eloquent\Builder object.

Is eloquent an ORM?

Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. An ORM is software that facilitates handling database records by representing data as objects, working as a layer of abstraction on top of the database engine used to store an application's data.

What is eloquent collection?

The Eloquent collection object extends Laravel's base collection, so it naturally inherits dozens of methods used to fluently work with the underlying array of Eloquent models. Be sure to review the Laravel collection documentation to learn all about these helpful methods!


3 Answers

You are returning a collection, not keeping the query open to update. Like your example is doing.

$models = MyModel::whereIn('id',[1,2,3]);
$models->update(['att'=>'foo']);

whereIn will query a column in your case id, the second parameter is an array of the ids you want to return, but will not execute the query. The findMany you were using was executing it thus returning a Collection of models.

If you need to get the model to use for something else you can do $collection = $models->get(); and it will return a collection of the models.

If you do not just simply write it on one line like so;

MyModel::whereIn('id',[1,2,3])->update(['att'=>'foo']);

Another option which i do not recommend is using the following;

$models = MyModel::findMany([1,2,3]);

$models->each(function ($item){
    $item->update(['att'=>'foo']);
});

This will loop over all the items in the collection and update them individually. But I recommend the whereIn method.

like image 100
Matt Burrow Avatar answered Oct 01 '22 11:10

Matt Burrow


The best solution in one single query is still:

MyModel::whereIn('id',[1,2,3])->update(['att'=>'foo']);

If you already have a collection of models and you want to do a direct update you can use modelKeys() method. Consider that after making this update your $models collection remains outdated and you may need to refresh it:

MyModel::whereIn('id', $models->modelKeys())->update(['att'=>'foo']);
$models = MyModel::findMany($models->modelKeys());

The next example I will not recommend because for every item of your $models collection a new extra query is performed:

$models->each(function ($item) {
    $item->update(['att'=>'foo']);
});

or simpler, from Laravel 5.4 you can do $models->each->update(['att'=>'foo']);

However, the last example (and only the last) is good when you want to trigger some model events like saving, saved, updating, updated. Other presented solutions are touching direct the database but models are not waked up.

like image 28
Marcel Avatar answered Oct 01 '22 11:10

Marcel


Just use the following:

MyModel::query()->update([
    "att" => "foo"
]);
like image 42
Unicco Avatar answered Oct 01 '22 11:10

Unicco