I found this wonderful resource https://learn2torials.com/a/laravel8-global-model-scope that takes us on a journey to know Scope. I will present the main points in a quick way, but increase the source and enjoy the article
- Global Scope
Let's create a new class under app/Scopes/HasActiveScope.php file with following contents
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class HasActiveScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('active', true);
}
}
you should override the model's booted method and invoke the model's addGlobalScope method. The addGlobalScope method accepts an instance of your scope as its only argument
<?php
namespace App\Models;
use App\Scopes\HasActiveScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
// using seperate scope class
static::addGlobalScope(new HasActiveScope);
// you can do the same thing using anonymous function
// let's add another scope using anonymous function
static::addGlobalScope('delete', function (Builder $builder) {
$builder->where('deleted', false);
});
}
use global scope
# fetching all active and non-deleted users
$users = User::all();
# above query will result in following sql
select * from `users` where `active` = 1 and `deleted` = 0
- Remove Scope From Query
you might not want your global filter to apply. For example, if you want to fetch all users weather they are active or not. In that case you can remove your applied scope using following example
# fetch all users weather they are active or not
$users = User::withoutGlobalScope(new HasActiveScope)->all();
# fetch active users weather they are deleted or not
User::withoutGlobalScope('delete')->all();
- Local Scope
Local scopes are prefixed using Scope keyword. In this case instead of defining global scope you can add local scope in your Laravel model like following
<?php
namespace App\Models;
use App\Scopes\HasActiveScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function scopeDelete($query)
{
return $query->where('delete', 0);
}
}
use local scope
# apply active local scope to following query
$users = User::active()->orderBy('created_at')->get();
# apply delete local scope to following query
$users = User::delete()->orderBy('created_at')->get();
- Dynamic Scopes
Sometime you may want to pass additional parameter to your local scope. In that case we can pass dynamic parameter to our local scope and it will act as dynamic scope
<?php
namespace App\Models;
use App\Scopes\HasActiveScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function scopeDelete($query)
{
return $query->where('delete', 0);
}
public function scopeWithRole($query, $role)
{
return $query->where('role', $role);
}
}
use dynamic scopes
# find active users with role admin
$users = User::active()->withRole('admin')->all();
I hope you enjoyed the article and I hope you always enjoy the code .
Top comments (0)