Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding scopes to parent model in Laravel

Tags:

php

laravel

I am attempting to clean up my code in my Laravel models at the moment and at the moment I have a lot of code duplication with local scopes in each model. Each model has a lot of similar columns that relate and I am figuring out how I can put these scopes in a single place but still be able to pass the $table variable so it can be used dynamically.

What I currently have in a few models for example

public function scopeName($query, $name)
{
    return $query->where($this->table.'name', $name);
}

public function scopeStatus($query, $status)
{
    return $query->where($this->table.'.status', $status);
}

I want to take these common scopes and have them in a single class where I can pass the table to it and then I can eliminate the code duplication. Haven't been able to find anything similar with extending the parent Model. I am also aware of global scopes but that still creates a similar issue where I am typing static::addGlobalScope(new StatusScope) in each model.

Any help is greatly appreciated.

Would using a trait be considered a bad option here?

like image 791
Countach Avatar asked Dec 24 '22 17:12

Countach


2 Answers

Trait is better here than inheritance, read more: https://en.wikipedia.org/wiki/Composition_over_inheritance

You can create a new trait for it:

trait CommonScopesTrait
{
    public function scopeName($query, $name)
    {
        return $query->where($this->table.'name', $name);
    }

    public function scopeStatus($query, $status)
    {
        return $query->where($this->table.'.status', $status);
    }
}

And use it in your model(s):

class YourModel extends Model
{
    use CommonScopesTrait;
}
like image 142
Alies Avatar answered Jan 10 '23 20:01

Alies


In addition to the answer of lptn, there is another option, which is also quite nice.

Create a basic model which you extend to Eloquent:

class BasicScope extends Eloquent {
    public function scopeName($query, $name)
    {
        return $query->where($this->table.'name', $name);
    }

    public function scopeStatus($query, $status)
    {
        return $query->where($this->table.'.status', $status);
    }
}

And then extend your own models on the BasicScope model, so you will have those methods available:

class User extends BasicScope {

}
like image 35
Douwe de Haan Avatar answered Jan 10 '23 20:01

Douwe de Haan