1
votes

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

User Model :

public function products()
{
    return $this->hasMany('App\Product');
}

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 Illuminate\Database\Eloquent\Relations\HasMany::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('App\User');
}

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 App\Product::App{closure}() must be an instance of App\Builder, instance of Illuminate\Database\Eloquent\Builder given


SOLVED

use Illuminate\Database\Eloquent\Builder
2

2 Answers

1
votes

Because products() method return Illuminate\Database\Eloquent\Relations\HasMany 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 Illuminate\Database\Eloquent\Builder
0
votes

I am not using Laravel, but:

Your ->where/->hasMany seems to return different (internal) object that does not contain your custom method.

To chain properly, return $this only:

class FooBar extends \Illuminate\Database\Eloquent
{

    public function products()
    {
        $this->hasMany('App\Product');

        return $this;
    }

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

        return $this;
    }
}