Eloquent hasManyThrough: jumping deeper into relationships

Quite often in bigger projects there are DB relationships with more than one level: categories->companies->products, countries->teams->players and similar. If we need to get the list of a deeper level, there’s a quick way of doing that with Eloquent.

Let’s take one of the examples above: product categories, each with companies, each company with products. What if we want to get the list of products by category?

Simplified DB structure:
categories
– id
– name

companies
– id
– category_id
– name

products
– id
– company_id
– name

So, in our Category model we should probably have companies() with hasMany(‘App\Company’) relationship, and in the model Company there should be products() method with another hasMany(‘App\Product’) relationship. That’s fine, but let’s go a level deeper – meet function hasManyThrough().

class Category extends Model
{
    /**
     * Get all of the products for the category.
     */
    public function products()
    {
        return $this->hasManyThrough('App\Product', 'App\Company');
    }
}

Now, if in the code you call $category->products – you will have a perfectly valid list of Product instances.

Please notice the order of parameters – first parameter is the final deepest third-level class, and then comes the middle-part class.

Another quick tip – if you need to specify columns for the relationships, you can do that by adding more parameters at the end:

public function products()
{
  return $this->hasManyThrough('App\Product', 'App\Company', 
    'category_id', 'company_id');
}
Like our articles?
Check out our Laravel online courses!

1 COMMENT

  1. Is there a way to have a hasManyThrough with a Many-to-Many relationship?

    A course can have many modules, a module belongs to a course.
    A module can have many lessons, but lessons can be in many modules.
    How would you write that a Course has many lessons through modules?

LEAVE A REPLY

Please enter your comment!
Please enter your name here