Reputation: 2661
I created a command in Laravel to run on a task schedule.
Here is the command logic:
public function handle()
{
$commentNotifications = CommentNotification::where('task_performed', 0)
->get();
foreach ($commentNotifications as $commentNotification) {
//blah blah
}
$commentNotifications->update(['task_performed' => 1]);
$this->comment(sprintf('Completed %d CommentNotification(s)', $commentNotifications->count()));
}
however this returned the following error:
Method Illuminate\Database\Eloquent\Collection::update does not exist.
So I tried this instead:
$commentNotifications->task_performed = 1;
$commentNotifications->save();
but this returned:
Method Illuminate\Database\Eloquent\Collection::save does not exist.
Why is this happening?
Upvotes: 0
Views: 761
Reputation: 3040
There are two issues here. One is your understanding of the Eloquent collection, and then your need to update multiple records with a single query.
Firstly, a collection is just a set of in-memory records that you can iterate through. The Eloquent collection is just an extension of that, where those records are pulled from a database, and typically has a set of models as the underlying items. It also has some extra methods to work with those models.
However, it is not directly tied to the database at all. This means that functions like update wouldn't work, and hence they do not exist.
For your need to update multiple records in the collection, you don't need to load them into memory first (unless you want to use them elsewhere). Simply create a query using the Builder, and call update on that query
CommentNotification::where('task_performed', 0)->update(['task_performed' = 1]);
This will create the expected SQL query:
UPDATE comment_notifications SET task_performed = 1 WHERE task_performed = 0;
Edit - To answer your query about the mass update:
If you need to only update a subset of records, you simply need to add a extra filter to the update
CommentNotification::whereIn('id', [1, 2, 3])
->where('task_performed', 0)
->update(['task_performed' = 1]);
This will update only the records with those IDs, and then only if the task is not performed. How you source the array of id values will be up to you.
Upvotes: 2
Reputation: 1
->get()
returns a collection.
Use a loop to update:
public function handle()
{
$commentNotifications = CommentNotification::where('task_performed', 0)
->get();
foreach ($commentNotifications as $commentNotification) {
$commentNotification->task_performed = 1;
$commentNotification->save();
}
$this->comment(sprintf('Completed %d CommentNotification(s)', $commentNotifications->count()));
}
Or, use Mass Updates.
CommentNotification::where('task_performed', 0)->update(['task_performed' => 1]);
Upvotes: 0
Reputation: 1296
you are using get() returns a collection therefore you cannot use update and save since they are methods of the eloquent model class use first() to get the first model instead of a collection , or use the update inside the foreach to update each item in your collections .
save() and update() exist in Illuminate\Database\Eloquent\Model;
for example
foreach ($commentNotifications as $commentNotification) {
$commentNotification->update(['task_performed' => 1]);
}
Upvotes: 0