Scope in Model - Laravel
Tags: laravel, php, beginners, webdev
Published: 2022-11-13 07:56:56

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
<?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
<?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
```php
# 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
```php
# 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
<?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
```php
# 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
<?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
```php
# 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 .