The "has-many-through" relationship provides a convenient shortcut for accessing distant relations via an intermediate relation. For example, a Country
model might have many Post
models through an intermediate User
model. In this example, you could easily gather all blog posts for a given country. Let's look at the tables required to define this relationship:
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
Though posts
does not contain a country_id
column, the hasManyThrough
relation provides access to a country's posts via $country->posts
. To perform this query, Eloquent inspects the country_id
on the intermediate users
table. After finding the matching user IDs, they are used to query the posts
table.
Now that we have examined the table structure for the relationship, let's define it on the Country
model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
/**
* Get all of the posts for the country.
*/
public function posts()
{
return $this->hasManyThrough('App\Models\Post', 'App\Models\User');
}
}
The first argument passed to the hasManyThrough
method is the name of the final model we wish to access, while the second argument is the name of the intermediate model.
Typical Eloquent foreign key conventions will be used when performing the relationship's queries. If you would like to customize the keys of the relationship, you may pass them as the third and fourth arguments to the hasManyThrough
method. The third argument is the name of the foreign key on the intermediate model. The fourth argument is the name of the foreign key on the final model. The fifth argument is the local key, while the sixth argument is the local key of the intermediate model:
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
'App\Models\Post',
'App\Models\User',
'country_id', // Foreign key on users table...
'user_id', // Foreign key on posts table...
'id', // Local key on countries table...
'id' // Local key on users table...
);
}
}
Example how to use this relationship:
$country = Country::find(1);
dd($country->posts);
Example 2:
Let us say we have three models.
- Team (id, name)
- User (id, name, team_id)
- Goal (id, user_id)
Now, inside User.php file. we can define the following relationships.
- User hasMany Goals.
- User belongsTo Team.
// User.php
public function goals()
{
return $this->hasMany(Goal::class);
}
public function team()
{
return $this->belongsTo(Team::class);
}
Next step inside Goal.php file, we can define the following relationship.
- Goal belongsTo User
// Goal.php
public function user()
{
return $this->belongsTo(User::class);
}
Finally, inside Team.php, we can define the following relationship.
- Team hasMany User
// Team.php
public function users()
{
return $this->hasMany(User::class);
}
the goal_id is not associated directly with the Team model.
The goal_id associated with the User model.
So, to get all goals of a team we can collect all the goals through the User model.
In that case, we can define the relationship like below inside Team.php model.
// Team.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public function users()
{
return $this->hasMany(User::class);
}
public function goals()
{
return $this->hasManyThrough(Goal::class, User::class);
}
}
Example how to get goals from team:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Team;
class TeamController extends Controller
{
public function show(Team $team)
{
$goals = $team->goals()->get();
}
}