Sau khi đã học One To One, One To Many và Many To Many, chúng ta sẽ tìm hiểu thêm một kiểu Relationship đặc biệt của Eloquent là Has Many Through.
Kiểu quan hệ này cho phép truy cập các bản ghi ở bảng cuối cùng thông qua một Model trung gian mà không cần tự viết câu lệnh JOIN.
Has Many Through là gì?
Has Many Through là quan hệ một - nhiều - nhiều.
Ví dụ:
Một Country có nhiều User.
Một User có nhiều Post.
Suy ra:
Một Country có nhiều Post thông qua User.
Sơ đồ:
Country
│
└──── User
│
├── Post
├── Post
└── Post
Country không liên kết trực tiếp với Post.
Laravel sẽ đi qua bảng User.
Ví dụ cơ sở dữ liệu
Bảng countries
| id | name |
|---|---|
| 1 | Việt Nam |
| 2 | Nhật Bản |
Bảng users
| id | name | country_id |
|---|---|---|
| 1 | An | 1 |
| 2 | Bình | 1 |
| 3 | Ken | 2 |
Bảng posts
| id | title | user_id |
|---|---|---|
| 1 | Laravel | 1 |
| 2 | PHP | 2 |
| 3 | MySQL | 3 |
Quan hệ:
Country
↓
Users
↓
Posts
Khai báo Relationship
Model Country:
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
Post::class,
User::class
);
}
}
Ý nghĩa:
Bắt đầu từ
Country.Đi qua
User.Lấy tất cả
Post.
Lấy dữ liệu
$country = Country::find(1);
$posts = $country->posts;
Hoặc:
foreach ($country->posts as $post) {
echo $post->title;
}
Laravel sẽ tự tạo các câu lệnh JOIN cần thiết.
SQL tương đương
Laravel sẽ sinh câu lệnh có ý tưởng tương tự:
SELECT posts.*
FROM posts
JOIN users
ON posts.user_id = users.id
WHERE users.country_id = 1;
Bạn không cần tự viết SQL.
eager loading
Có thể tải trước:
$countries = Country::with('posts')->get();
Sau đó:
foreach ($countries as $country) {
echo $country->name;
foreach ($country->posts as $post) {
echo $post->title;
}
}
Điều này giúp giảm số lượng truy vấn.
Một ví dụ thực tế
Giả sử hệ thống bán hàng:
Customer
│
▼
Order
│
▼
OrderItem
Một Customer có nhiều Order.
Một Order có nhiều OrderItem.
Ta có thể khai báo:
public function orderItems()
{
return $this->hasManyThrough(
OrderItem::class,
Order::class
);
}
Khi đó:
$customer->orderItems;
sẽ trả về toàn bộ sản phẩm mà khách hàng đã đặt.
Khi nào nên dùng?
Has Many Through phù hợp khi:
Muốn truy cập dữ liệu gián tiếp.
Không muốn tự viết JOIN.
Muốn giữ mã nguồn ngắn gọn và dễ đọc.
Ví dụ:
Country → Posts.
Customer → OrderItems.
Company → Employees thông qua Department.
School → Students thông qua ClassRoom.
So sánh
| Relationship | Ví dụ |
|---|---|
| One To One | User → Profile |
| One To Many | User → Posts |
| Many To Many | Post ↔ Tags |
| Has Many Through | Country → Posts → User |
Tổng kết
Trong bài này chúng ta đã học:
Khái niệm Has Many Through.
Truy cập dữ liệu thông qua Model trung gian.
Khai báo
hasManyThrough().Lấy dữ liệu bằng Eloquent.
with()để tối ưu truy vấn.
Đây là một Relationship mạnh mẽ giúp giảm đáng kể số lượng câu lệnh JOIN thủ công trong các dự án lớn.
Bài tập
Tạo model
Country.Thêm khóa ngoại
country_idvào bảngusers.Khai báo
hasManyThrough()trong modelCountry.Hiển thị tất cả Post của Country có
id = 1.Sử dụng
with('posts')để lấy danh sách Country cùng các Post liên quan.
Bài tiếp theo
Ở bài sau, chúng ta sẽ tìm hiểu Polymorphic Relationship, một kiểu quan hệ linh hoạt cho phép nhiều Model khác nhau cùng chia sẻ một bảng dữ liệu, chẳng hạn như Post và Video đều có thể sử dụng chung bảng comments.
x0




Không có nhận xét nào:
Đăng nhận xét