Search code examples
laravellaravel-models

Laravel: active column that behave like softdelete


I have a model accounts in Laravel that uses Softdeletes. Beside that, I want another column called active, that behaves kinda the same. If its sets to XXX then all Account:: calls shouldnt include them in the return. Until I set the active value to YYY, after this, they should be included. Is there any way to do this? I want to set the XXX and YYY values by my own. So I could say return only if active = 1 or active = whatEverIWant

Edit: I know I could do that by checking the value at every call, but I already use the accounts at a lot of places and dont want to add it everywhere


Solution

  • Can be approached in two ways

    Option 1: Global Scope

    You can define a global scope on the model, which returns records only with active set to 1

    class Account extends Model
    {
    
        protected static function booted()
        {
            static::addGlobalScope('active', function (Builder $builder) {
                $builder->where('active', 1);
            });
        }
    
        // rest of the class code
    }
    

    Now all the queries on the model will have the constraint defined in global scope.

    When you do want to retrieve records irrespective of whether active is set to 1 not, you can call it with withoutGlobalScopes() or withoutGlobalScope('active') - will remove the constraint defined in global scope.

    $accounts = Account::withoutGlobalScopes()->get();
    
    //OR
    
    $accounts = Account::withoutGlobalScope('active');
    

    Option 2: Local Scope

    You can define a local scope on the model class for each of active and inactive states

    class Account extends Model
    {
        public function scopeActive($query)
        {
            $query->where('active', 1);
        }
    
        public function scopeInactive($query)
        {
            $query->where('active', '<>', 1);
        }
    }
    

    Then when you want to filter records which are active or inactive

    $activeAccounts = Account::active()->get();
    
    $inactiveAccounts = Account::inactive()->get();
    
    $accounts = Account::get(); //to get all records irrespective of whether active or inactive
    

    Laravel softdeletes also uses scopes behind the scenes.

    Laravel docs: https://laravel.com/docs/master/eloquent#query-scopes