mrkarma4ya's avatar

Need help creating a mixed relationship

I have 3 models - Company, License and User

The relation between them is like this:

Company -> hasMany -> License -> belongsTo -> User

Inversely,

User-> hasMany -> License -> belongsTo -> Company

So, in database I have company_id and user_id columns in licenses table

Now, I want to get a relation between company and user through license. HasManyThrough doesn't work here as its a mix of hasMany and belongsTo.

How can I do it?

0 likes
3 replies
LaryAI's avatar
Level 58

One solution to this problem is to define a custom relationship method on the Company model that uses a nested eager loading query to retrieve the related User models through the License model. Here's an example implementation:

class Company extends Model
{
    public function users()
    {
        return $this->hasManyThrough(
            User::class,
            License::class,
            'company_id', // Foreign key on licenses table
            'id', // Local key on users table
            'id', // Local key on licenses table
            'user_id' // Foreign key on users table
        )->with('licenses');
    }
}

This method defines a hasManyThrough relationship between the Company and User models, using the License model as an intermediate model. The foreign key on the License model that references the Company model is 'company_id', and the foreign key on the User model that references the License model is 'user_id'.

The key to making this work is the 'with' method call at the end of the relationship definition. This tells Laravel to eager load the related License models for each User model that is retrieved through the hasManyThrough relationship. This allows us to access the Company model for each License model, completing the mixed relationship.

With this relationship defined, you can now retrieve all the User models related to a Company model like this:

$company = Company::find(1);
$users = $company->users;

This will return a collection of User models, each with their related License models and the Company model that owns those licenses.

tisuchi's avatar

@mrkarma4ya How about this?

In Company.php model:

    public function users()
    {
        $userIds = License::where('company_id', $this->id)
            ->pluck('user_id')
            ->unique()
            ->toArray();

        return User::whereIn('id', $userIds)->get();
    }

in User.php model:

public function companies()
    {
        $companyIds = License::where('user_id', $this->id)
            ->pluck('company_id')
            ->unique()
            ->toArray();

        return Company::whereIn('id', $companyIds)->get();
    }

Please or to participate in this conversation.