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

hfalucas's avatar

Listing a User's Products by Category in Eloquent

Model excerpt

Basically I have the following tables and I'm trying to list for a given user all his products by category.

Example:

    {
     user_id: 1
     username: xpto
       categories: [{
          id: 1
          name: category_1
            products: [{
              id: 3
              name: prod1
            },
            {
              id: 3
              name: prod1
            }],
          id: 2
          name: category_2
            products: [{
              id: 6
              name: prod5
            }],
        }]
    }

The closest I got from my desired result was with this query: App\User::with('products.category')->find(1);

Already spent a lot of hours thinking about this, but no clue, starting to feel desperate. Help please.

0 likes
28 replies
JarekTkaczyk's avatar
Level 53

@hfalucas There's no easy way when you're querying user, but just do this:

$userId = 1;

$callback = function ($q) use ($userId) {
  $q->where('users.id', $userId);
};

$categories = Category::with(['products' => function ($q) use ($callback) {
   // get only products of the user
   $q->whereHas('users', $callback);
}])
  // get only categories of the user (through products)
  ->whereHas('products.users', $callback)
  ->get();
3 likes
pmall's avatar

Damed jarek eloquent as no secret for you.

I was thinking the same with nested whereHas. Dot notation works with whereHas really ?

pmall's avatar
public function products()
{
  return $this->belongsToMany('Product')->withPivot('the attribute you want');
}

:)

hfalucas's avatar

I'm doing that @pmall :)

The thing is with that query I can't access the pivot table.

hfalucas's avatar

Thinking better I don't really think I need it xD

JarekTkaczyk's avatar

@hfalucas Access in the query? You can do it of course:

$callback = function ($q) use ($userId) {
  $q->where('users.id', $userId)
      ->where('product_user.some_column', 'some_value');
};
pmall's avatar

I hate this thread :D The schema is obvious. The wanted result is quite basic, but it is hell to execute this query.

hfalucas's avatar

@JarekTkaczyk not access them in the query, I mean print them too. Lets say product_user table has more fields other then the id's is possible to include them in the final result?

In my models I added them ->withPivot('field1, field2') but it seems that the relationship is "lost"(don't know how to put this) with the whereHas.

JarekTkaczyk's avatar

@hfalucas Yes, withPivot is the way. Show me the query and the result - I can't guess what you mean by lost here :)

hfalucas's avatar

@JarekTkaczyk The query is the one you posted above :)

I'm just trying to also add the fields from the pivot table.

hfalucas's avatar

@JarekTkaczyk The query works the same with or without withPivot(). This means it returns the products nested under the respective category.

Like this:

- cat1
    - prod1
    - prod2
- cat3
    - prodN          

What I mean when trying to display the items on the pivot table is:

- cat1
    - prod1
    - pivot_field_1
   (...)

which was possible never possible (it probably is...I'm just stupid) with your query :)

Hope this makes sense.

JarekTkaczyk's avatar

@hfalucas Oh, ok. You just don't know how to access pivot fields :)

So, when object is loaded in the context of belongsToMany relation, then it has pivot model attached:

$category->pivot->field_1

and so on.

JarekTkaczyk's avatar

@hfalucas Do you have pivot in hidden fields maybe? Was it there before adding withPivot? I can't guess :) It just is there always, so you must have done something wrong.

hfalucas's avatar

@JarekTkaczyk I don't have the pivot fields in hidden fields property and the pivot table was never there from the beginning(with and without withPivot). :(

I set up a quick project with only the referred models so you can see (if you have a chance) what I'm talking about.

https://github.com/hfalucas/query-problem

(the query is in the routes file)

JarekTkaczyk's avatar

@hfalucas Well my friend, you have Category hasMany Product, so there is no pivot involved. It will be there for products-users relation. All is good there!

And btw when you push something like this again, include seeder, so anyone can just run artisan migrate --seed and have the same data as you do.

hfalucas's avatar

Exactly @JarekTkaczyk :D between categories and products there is no pivot table, what I am trying to access is the products-users relation, in order tho achieve something like this (if it is even possible)

 - category_1 
       - product_1 
               - product_user_some_field // field from the users_product table 
 (and so on)

All of that for a given user of-course. So for a given user I be able to list all his products(with the product_user table fields included) grouped by the categories.

Probably my whole schema is wrong and it is not possible to do what I want, if so do you have any suggestions? Also hope i explained my self clear, don't really wanna sound annoying you have been super patient so far :)

PS: I really should had included the seed files, my bad :(

JarekTkaczyk's avatar

@hfalucas Well, then you need to load users as well:

with(['products' => function ($q) {...}, 'products.users']) ...

Then you will have pivot fields available on each user: user->pivot->field_1.

Please or to participate in this conversation.