Rebase a query builder after filtering an Eloquent Collection
Sometimes after retrieving models from database, you will need to apply some filtering from your PHP code and then execute a query on the models remaining in the collection.
Let say you want to retrieve all 3nth logged in users:
$loggedInUsers = User::where('logged_in', true)->get();
$nthUsers = $loggedInUsers->nth(3);
And then you want to update them:
$nthUsers->update(/* ... */);
The below code won't work, because the nth
method returns an instance of Illuminate\Support\Collection
and not an instance of Illuminate\Database\Eloquent\Collection
.
This is the case for all the methods which are not overriden from the Eloquent Collection class.
But still, there is a solution, the Eloquent Collection includes a method called toQuery
which "rebuild" the query builder, using the first model instance of the collection, and the keys of each models still present in the collection.
if ($nthUsers->isNotEmpty()) {
$nthUsers->toQuery()->update(/* ... */);
}
Here is a simplified version of the toQuery
method
public function toQuery()
{
$model = $this->first();
return $model
->newModelQuery()
->whereKey($this->modelKeys());
}
The original method secure the way you use it, so you can't call it if:
- The collection is empty (because
$this->first()
will fail) - The collection contains models from multiple tables (which could be the case when retrieve polymorphic relationships)
Comments
Be the first to post a comment!