Skip to content
Advertisement

How to add new method chaining for Laravel Eloquent?

I try to add new method for simplify and reusable code but I failed

User Model :

public function products()
{
    return $this->hasMany('AppProduct');
}

public function obsolate()
{
    return $this->where('status', 'obsolate');
}

When I try to retrieve like auth()->user()->products()->obsolate() it gives some error like

BadMethodCallException: Call to undefined method IlluminateDatabaseEloquentRelationsHasMany::obsolate()

But If I do like auth()->user()->products()->where('status', 'obsolate')->get() It works.

Please, correct me if I wrong…


UPDATE

Product Model :

public function user()
{
    return $this->belongsTo('AppUser');
}

public function scopeObsolate($query)
{
    return $query->where('status', 'obsolate');
}

I do auth()->user()->products->obsolate()->get() and it works!

But, if I want to use constraint group to solve this problem it will return error

public function scopeObsolate(Builder $builder)
{
    return $builder->where(function (Builder $query) {
        return $query->where('status', 'obsolate');
    });
}

Argument 1 passed to AppProduct::App{closure}() must be an instance of AppBuilder, instance of IlluminateDatabaseEloquentBuilder given


SOLVED

use IlluminateDatabaseEloquentBuilder

Advertisement

Answer

Because products() method return IlluminateDatabaseEloquentRelationsHasMany object. When you applying where to it, laravel will set the constraints on the relation query(It means Product eloquent builder). So you need to defined the method in Product model.

And change the obsolate method to scope method:

// Product model:
public function scopeObsolate($query)
{
    return $query->where('status', 'obsolate');
}

Update:

The second error occurs because the type-hint, laravel cannot find the Builder in model. You need to

use IlluminateDatabaseEloquentBuilder
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement