Ở bài trước, chúng ta đã tìm hiểu quan hệ One To One, trong đó mỗi bản ghi chỉ liên kết với duy nhất một bản ghi khác.
Trong thực tế, quan hệ One To Many xuất hiện thường xuyên hơn rất nhiều.
Ví dụ, một người dùng có thể viết nhiều bài viết, một danh mục có thể chứa nhiều bài viết hoặc một đơn hàng có nhiều sản phẩm.
Laravel hỗ trợ kiểu quan hệ này rất đơn giản thông qua hai phương thức hasMany() và belongsTo().
One To Many là gì?
One To Many là quan hệ một - nhiều.
Ví dụ:
Một User có nhiều Post.
Một Category có nhiều Post.
Một Customer có nhiều Order.
Sơ đồ quan hệ:
User (1)
│
├── Post 1
├── Post 2
├── Post 3
└── ...
Cơ sở dữ liệu
Bảng users
| id | name |
|---|---|
| 1 | Nguyễn Văn A |
| 2 | Trần Văn B |
Bảng posts
| id | title | user_id |
|---|---|---|
| 1 | Laravel | 1 |
| 2 | PHP | 1 |
| 3 | MySQL | 2 |
Mỗi bài viết chỉ thuộc về một User, nhưng một User có thể sở hữu nhiều bài viết.
Migration
Trong bảng posts, tạo khóa ngoại:
$table->foreignId('user_id')
->constrained()
->cascadeOnDelete();
Laravel sẽ tự liên kết tới bảng users.
hasMany()
Trong model User:
class User extends Authenticatable
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
Ý nghĩa:
Một User có nhiều Post.
Laravel sẽ mặc định tìm khóa ngoại user_id.
belongsTo()
Trong model Post:
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
Ý nghĩa:
Mỗi Post thuộc về một User.
Lấy tất cả bài viết của User
$user = User::find(1);
$posts = $user->posts;
Hiển thị:
foreach ($user->posts as $post) {
echo $post->title;
}
Laravel sẽ tự truy vấn bảng posts.
Lấy User của một Post
$post = Post::find(1);
echo $post->user->name;
Laravel sẽ truy vấn bảng users.
Tạo Post cho User
Thay vì tự gán user_id, có thể tạo trực tiếp thông qua Relationship.
$user = User::find(1);
$user->posts()->create([
'title' => 'Laravel 12',
'content' => 'Bài viết đầu tiên'
]);
Laravel sẽ tự động thêm:
user_id = 1
Đây là cách được khuyến khích sử dụng trong Eloquent.
Đếm số lượng Post
Có thể đếm nhanh:
$user->posts()->count();
Hoặc:
echo $user->posts->count();
Cách đầu tiên tối ưu hơn vì Laravel chỉ thực hiện câu lệnh COUNT(*) trên cơ sở dữ liệu.
eager loading
Nếu hiển thị danh sách User cùng các Post:
$users = User::with('posts')->get();
Sau đó:
foreach ($users as $user) {
echo $user->name;
foreach ($user->posts as $post) {
echo $post->title;
}
}
Sử dụng with() giúp tránh hiện tượng N+1 Query, giảm số lượng truy vấn và tăng hiệu năng.
Lấy User cùng số lượng Post
Laravel hỗ trợ withCount():
$users = User::withCount('posts')->get();
Sau đó:
echo $user->posts_count;
Rất hữu ích khi hiển thị thống kê.
Một ví dụ khác
Quan hệ One To Many không chỉ dùng cho User và Post.
Ví dụ:
Category
│
├── Laravel
├── PHP
├── MySQL
└── JavaScript
Model Category:
public function posts()
{
return $this->hasMany(Post::class);
}
Model Post:
public function category()
{
return $this->belongsTo(Category::class);
}
Đây cũng là một quan hệ One To Many rất phổ biến trong các hệ thống Blog hoặc CMS.
Tổng kết
Trong bài này chúng ta đã học:
Quan hệ One To Many.
hasMany().belongsTo().Lấy danh sách bản ghi liên quan.
Tạo dữ liệu thông qua Relationship.
with()để tối ưu truy vấn.withCount()để thống kê số lượng bản ghi.
One To Many là kiểu Relationship được sử dụng nhiều nhất trong Laravel và là nền tảng cho hầu hết các ứng dụng quản lý dữ liệu.
Bài tập
Khai báo quan hệ
hasMany()trong modelUser.Khai báo quan hệ
belongsTo()trong modelPost.Hiển thị tất cả bài viết của User có
id = 1.Hiển thị tên tác giả của một Post.
Tạo một Post mới thông qua
$user->posts()->create().Hiển thị số lượng bài viết của từng User bằng
withCount().
Bài tiếp theo
Ở bài sau, chúng ta sẽ tìm hiểu Many To Many, kiểu quan hệ cho phép nhiều bản ghi của bảng này liên kết với nhiều bản ghi của bảng khác thông qua bảng trung gian (Pivot Table).
x1




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