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

coolAngel's avatar

Joining 3 Tables?

Hi, I am know to Laravel word and programming.

Joining 2 tables is easy with hasMany relation.But how can I Join 3 tables? Say that, in my mind there is a simple app about movies. A movie has a few Factors and each Factor has a Role in the Movie.

So 3 Models = 3 tables 1.Movie = movies 2.Factor = factors 3.Role =roles

And the table will join the factor_movie_role*(1) with 3 col factor_id, movie_id, role_id

why I think it like that? Because a factor(Jefry Way) is the role(director) of movie(Need more?:Laracasts) but also is the role(storyteller).

(1) wich is the best practice for naming a pivot table like this

0 likes
9 replies
coolAngel's avatar

It's close but not what I try to do

table movies
    id - integer
    title - string   (like )

table roles
    id - integer
    name - string    (like "Actor", "Director")

table factors
    id - integer
    name - sting  (like "John Doe", "Melanie Doe") 

table factor_movie_role
    factor_id - integer   1 john doe       2 Melanie Doe
    movie_id - integer   1 one movie    1 one movie
    role_id - integer      2 director       1 Actor 

so..

SELECT * FROM factor_movie_role
    INNER JOIN factors ON factor_movie_role.factor_id = factors.id
    INNER JOIN movies ON factor_movie_role.movie_id = movies.id
    INNER JOIN roles ON factor_movie_role.role_id = roles.id
psmail's avatar

This comes up a lot. I too have this question and have no definitive answer.

What I can say is that you can create table with the three foreign keys and then treat that table as the pivot table. Laravel pivot queries only support two foreign keys, but you can treat an extra column of information using standard Laravel pivot syntax

But here's the problem - because Laravel doesn't do three way pivots out of the box, standard eloquent won't always - read, often - give the results you expect. So I found myself using DB:: far more often than I would have liked.

1 like
bashy's avatar

Not sure how it wouldn't work, just do a pivot for each one and include them where the ID equals the same one?

MartelliEnrico's avatar

Have you tried something like this?

class Movie {

public function factors()
{
return $this->belongsToMany('Factor', 'factor_movie_role', 'movie_id', 'factor_id');
}

public function roles()
{
return $this->belongsToMany('Role', 'factor_movie_role', 'movie_id', 'role_id');
}

}

class Factor {

public function movies()
{
return $this->belongsToMany('Movie', 'factor_movie_role', 'factor_id', 'movie_id');
}

public function roles()
{
return $this->belongsToMany('Role', 'factor_movie_role', 'factor_id', 'role_id');
}

}

class Role {

public function movies()
{
return $this->belongsToMany('Movie', 'factor_movie_role', 'role_id', 'movie_id');
}

public function factors()
{
return $this->belongsToMany('Factor', 'factor_movie_role', 'role_id', 'factor_id');
}

}

With this, you should be able to do something like what @bashy said:

Movie::with('factors', 'roles')->all(); // or
Factor::with('movies', 'roles')->all(); // or
Role::with('factors', 'movies')->all();
psmail's avatar

@bashy it doesn't work where one table is used for all three pivots.

Why use one table? To guarantee a unique combination of foreign keys. This is a common requirement of the three way pivot.

What unexpected results does it return? Well if the first two of three foreign keys are the same and it is the third foreign key that differs but the laravel pivot involves the first two foreign keys ... Where a Common SQL query would return one record the eloquent review will return multiples. Which is understandable but undesirable.

2 likes
HermanMonster's avatar

Any update on this?

It's exactly what i need, read many solutions, but not a clean eloquent one.

jekinney's avatar

I've done a 4 way pivot table with the results @bashy described (already had SQL database and made to work with laravel and eloquent).

As we know you can set the table name and the columns to look up in the belongsToMany. It then doesn't matter really how many columns you have. Your telling eloquent when you query the relationship where and how to fetch the data you want.

Please or to participate in this conversation.