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

thorlucas's avatar

Complex relationships (hasManyThrough through a pivot table)

So I have four tables.

  • products
  • skus
  • sku_attribute
  • attributes

Each product has many skus. Each sku has many attributes. And each attribute can have several skus associated with it. sku_attribute is a pivot table for the many to many relationship between skus and attributes.

So we have the following relationships:

  • product hasMany sku
  • sku belongsToMany attribute (through sku_attribute pivot)
  • attribute belongsToMany sku (through sku_attribute pivot)

This works fine! But now, how do I get all the attributes associated with a product?

The following code would have worked for me.

public function attributes()
{
    return $this->skus->flatMap(function ($sku) {
        return $sku->attributes;
    });
}

But I get an error because this doesn't return a relationship but rather a collection.

I also tried using the solution found here. But I couldn't get it to work properly because their model is slightly different than mine. (Each product has many skus, not vice versa.)

Another solution was to include a third column on sku_attributes for the product_id, but I couldn't find a way to default fill this to sku->product->id on the $sku->attach($attribute_id) method. Instead I'd have to manually call this every time, like $sku->attach($attribute_id, ['product_id' => $sku->product->id]).

0 likes
4 replies
tpane24's avatar

This a complex situation for sure. Tell me what I am missing because it actually seems from your description that you already have solved this.

Your public function attributes() returns an Eloquent collection of all the attributes associated with a product does it not?

staudenmeir's avatar

There is no native support for this in Laravel.

I created a package for it: https://github.com/staudenmeir/eloquent-has-many-deep

You can use it like this:

class Product extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function attributes()
    {
        return $this->hasManyDeep(Attribute::class, [Sku::class, 'sku_attribute']);
    }
}
thorlucas's avatar

@TPANE24 - Yes, but unfortunately it's not a relationship. So I can't chain relationships to it.

tpane24's avatar

@thorlucas I see what you're saying. Now that you have a Collection of attributes, couldn't you just loop through those attributes using a whereIn clause and query the DB that way?

`public function attributes()
{
    return $this->skus->flatMap(function ($sku) {
        return $sku->attributes->toarray();  
    });
}

then you could just query.

DB::table('sku')->whereIn('product', 'variable holding above array/collection')->get();

Please or to participate in this conversation.