We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Scopes in Eloquent are a great way to define common sets of query constraints that you may easily re-use throughout your application.
They are usually defined inside the Model class:
namespace App\Models;
use Illuminate\Database\Eloquent\Builder
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function scopePopular(Builder $query): Builder
{
return $query->where('votes', '>', 100);
}
public function scopeActive(Builder $query): Builder
{
return $query->where('active', 1);
}
}
Once defined, you can use them like this:
use App\Models\User;
$users = User::popular()->active()->orderBy('created_at')->get();
One drawback is that sooner than later, you will get a lot of scopes in your model which clutters the code. It would be nice to have them in a separate class.
To achieve this, we'll create a custom Eloquent Builder. To create a custom builder, you need to create the appropriate class and it should extend Illuminate\Database\Eloquent\Builder
.
A custom builder should concern one, and only one, model.
In our example, the builder will be defined like this:
namespace App\Builders;
use Illuminate\Database\Eloquent\Builder;
class UserBuilder extends Builder
{
public function popular(): self
{
return $this->where('votes', '>', 100);
}
public function active(): self
{
return $this->where('active', 1);
}
}
What you can see is that you no longer need the scope
prefix neither do you need the $query
parameter as the function argument.
To use this in your model, you need to override the newEloquentBuilder method:
namespace App\Models;
use Illuminate\Database\Eloquent\Builder
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function newEloquentBuilder($query)
{
return new UserBuilder($query);
}
}
Usage is still exactly the same:
use App\Models\User;
$users = User::popular()->active()->orderBy('created_at')->get();
Thanks to this article for the idea.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.