Dev.W
Dev.W

Reputation: 2370

Laravel newQuery()

I've been looking at the newQuery eloquent model and best case uses and I can see the benefit in searching / filtering products based on a search page however is it possible to call the newQuery on only the Users related products?

For example, I have 2 models.

User has many products and I have the relationship defined on the user model.

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

Now, previously if I wanted to filter all the products and take user out of the scenario I could use:

$query = (new \App\Product)->newQuery();

if($request->get('category')){
  $query->whereHas('category',function($q) use($request){
     $q->where('category_id',$request->get('category'));
  });
}

$products = $query->get();

This is great and I like this method and I now want to have a similar functionality on only users products.

For example, id like to:

$products = (Auth::user()->products)->newQuery();

if($request->get('category')){
  $products->whereHas('category',function($q) use($request){
     $q->where('category_id',$request->get('category'));
  });
}

$products = $query->get();

But I can't do this I get newQuery() method is not available.

Is there a better way of performing optional queries based on parameters?

Upvotes: 3

Views: 10173

Answers (2)

Ben Swinburne
Ben Swinburne

Reputation: 26467

Just for a bit of neatness you can use the when() method on the builder class too

auth()->user()->products()
    ->when($request->category, function ($query) use ($request) {
        $query->whereCategoryId($request->category);
    })->get();

or

Product::whereUserId(auth()->id())
    ->when($request->category, function ($query) use ($request) {
        $query->whereCategoryId($request->category);
    })->get();

Upvotes: 2

Alexey Mezenin
Alexey Mezenin

Reputation: 163748

Change your code to this to make it work:

$products = Product::where('user_id', auth()->id());

if (request('category')) {
    $products = $products->whereHas('category', function($q) {
        $q->where('category_id', request('category'));
    });
}

$products = $products->get();

Alternatively, you could just load related products using lazy eager loading:

auth()->user()->load(['products' => function($q) {
    if (request('category')) {
        $q->whereHas('category', function($q) {
            $q->where('category_id', request('category'));
        });
    }
}]);

Upvotes: 3

Related Questions