Cả hai đều đi qua một bảng trung gian nhưng bản chất khác nhau.
belongsToMany— quan hệ nhiều-nhiều, bảng trung gian là pivot không có model riêng (role_user). Truy cập được dữ liệu pivot quawithPivot().hasManyThrough— quan hệ một-nhiều đi xuyên qua một model trung gian có thật. Không có pivot; chỉ là đường tắt cho hai lầnhasManyliên tiếp.
php
// Country -> User -> Post: lấy toàn bộ post của một quốc gia
class Country extends Model
{
public function posts(): HasManyThrough
{
return $this->hasManyThrough(
Post::class, // model đích
User::class, // model trung gian
'country_id', // FK trên users trỏ về countries
'user_id', // FK trên posts trỏ về users
'id', // local key trên countries
'id', // local key trên users
);
}
}
$country->posts; // 1 query JOIN thay vì lặp qua từng userÝ nghĩa thực tế: thay vì $country->users rồi lặp lấy $user->posts (N+1), Eloquent sinh một câu JOIN duy nhất. Có hasOneThrough cho biến thể một-một.
Đi sâu hơn 2 cấp thì hasManyThrough không đủ — lúc đó viết relation tuỳ biến bằng query builder hoặc thêm cột denormalize khoá cấp cao vào bảng đích.