Laravel Eloquent relationship chain (hasMany)

55 Views Asked by At

I have a list of Users.

I have a list of Businesses, and only ONE User is allocated the "admin" of that business. (the column for this is "user_id").

The User can be the "admin" of multiple Businesses.

I have a list of Training Programs, and only ONE Business can be the "admin" of that Program. (the column for this is "business_id")

By definition, the "admin" User of a business will also be the "admin" User of a Training Program (they have been given the role of admin for both the business and anything the business is connected to).

If I log in as a User, I can view a list of all the Businesses that I am the "admin" for. This is easy because the Business Model has the user_id column. In "User" Model":

    public function businesses(): HasMany
    {
        return $this->hasMany(Business::class, 'user_id');
    }

Great!

However I also want to return all Training Progams that I am, by definition as the "admin" of a Business, also the "admin" for. This isn't so easy, because there is no 'user_id' column in the Training Program, only a 'business_id'

What is the best way for me to create that relation via the User Model, rather than making multiple Eloquent calls (or Raw DB Joins)?

I tried chaining HasManys together, as I already have the businesses Relationship eg. In "User" Model":

    public function businesses(): HasMany
    {
        return $this->hasMany(Business::class, 'user_id');
    }

    public function trainingprograms(): HasMany
    {
        return $this->businesses->hasMany(Trainingprogram::class, 'user_id');
    }

...but this doesn't work. Is there a clean solution for this relationship from the User model?

thanks

1

There are 1 best solutions below

0
Delmontee On

Credit to @ZeNix for the answer.

The solution was to use hasManyThrough() in the User Model:

public function trainingprograms(): HasManyThrough
        {
            return $this->hasManyThrough(Trainingprogram::class, Business::class, 'user_id');
        }

The first argument passed to the hasManyThrough method is the name of the final model I need to access (Trainingprogram), while the second argument is the name of the intermediate model (Business) from where I can grab the final Model (Trainingprogram) info. 'user_id' is just the column name (in the Business Model/table) to reference the related logged in User. It would work without this value as "[model]_id" is inferred by default.