Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ehabafia's avatar

A Nested query

I have a Category / Products / Users I need to get all Categories of All Products for a specific user. I was able to make selecting a product for a specific User but I couldn't tell how to get all the categories of these products.

Products and Users relationship is ManyToMany. The relationship between product belongsTo Category and Category hasMany Products

Here is what I made:

$products = Product::byUser(auth()->id())->get();
public function scopeByUser(Builder $query)
{
    return $query->whereHas('users', function ($q) {
        $q->where('id', auth()->id());
    });
}

But I couldn't make it in a way to have:

$products = Category::productsByUser(auth()->id());

So that I can get all the categories and all the products of the loggedIn user.

0 likes
8 replies
Palak27's avatar

@ehabafia try this

$products = Category::with(['product '=> function($query)  {
      $query->byUser(auth()->id());
    }
 ])->get();
Mithrandir's avatar

So you want a list of Category objects that are connected to products for a specific user?

In other words, you want all Category objects that have products for a specific users. Or in Eloquent:

$categories = Category::whereHas('product', function($query) {
  $query->byUser();
})->get();

And - as @palak27 suggests - I would consider adding the ID of the user as a parameter to scopeByUser() to make it more usable in contexts where you want to use another user

ehabafia's avatar

Actually, What I am looking for is listing the Categories and along with each category the list of all the products that are related to that category for this user.

Snapey's avatar

so @palak27 solution should work for you... provided your scope is working as it should

ehabafia's avatar

It's showing a byUser method not defined. so, it's not catching the scopeByUser where I have it in the Category Model for some reason. isn't it correct to have it there or it should be in the Product model or User model.

ahmeddabak's avatar

The scope scopeByUser should stay in Product Model

ehabafia's avatar

Thank you all, it works fine, but the only thing is that it will show you the categories that have products in it and the categories that are empty. I found another solution that will eliminate that, but not sure if it's the optimum way of doing it. Please advise.

public function scopeByUser(Builder $query, $user_id)
{
    return $query->whereHas('products', function ($q) use ($user_id) {
        $q->whereHas('users', function ($q) use ($user_id) {
            $q->where('id', $user_id);
        });
    });
}

public function scopeProductsByUser(Builder $query, $user_id)
{
    $query->with(['products'=> function ($q) use ($user_id) {
        $q->whereHas('users', function ($q) use ($user_id) {
            $q->where('id', $user_id);
        });
    }])->byUser($user_id);
}

They both stay in the Category model, and I call them as:

$categories = Category::productsByUser(auth()->id())->get();

This way I got only the categories that has products in it for that user.

Please or to participate in this conversation.