Ở các bài trước, mỗi Relationship đều liên kết giữa các Model cố định.
Ví dụ:
User ↔ Profile
User ↔ Post
Post ↔ Tag
Tuy nhiên trong thực tế, có nhiều trường hợp nhiều Model khác nhau cùng chia sẻ một loại dữ liệu.
Ví dụ:
Post có Comment.
Video có Comment.
Product có Comment.
Nếu tạo riêng ba bảng bình luận thì sẽ rất khó quản lý.
Laravel giải quyết vấn đề này bằng Polymorphic Relationship.
Polymorphic Relationship là gì?
Polymorphic Relationship cho phép một bảng được dùng chung cho nhiều Model khác nhau.
Ví dụ:
Post
│
│
Video │──────► Comments
│
Product
Tất cả đều dùng chung bảng comments.
Ví dụ cơ sở dữ liệu
Bảng posts
| id | title |
|---|---|
| 1 | Laravel 12 |
Bảng videos
| id | title |
|---|---|
| 1 | Laravel Tutorial |
Bảng comments
| id | body | commentable_id | commentable_type |
|---|---|---|---|
| 1 | Hay quá | 1 | App\Models\Post |
| 2 | Rất hữu ích | 1 | App\Models\Video |
Thay vì dùng post_id hoặc video_id, Laravel sử dụng:
commentable_idcommentable_type
để xác định Comment thuộc về Model nào.
Migration
Ví dụ tạo bảng comments:
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('body');
$table->morphs('commentable');
$table->timestamps();
});
Lệnh:
$table->morphs('commentable');
sẽ tự tạo hai cột:
commentable_id
commentable_type
Đây là chuẩn của Laravel.
morphMany()
Trong model Post:
class Post extends Model
{
public function comments()
{
return $this->morphMany(
Comment::class,
'commentable'
);
}
}
Model Video cũng tương tự:
class Video extends Model
{
public function comments()
{
return $this->morphMany(
Comment::class,
'commentable'
);
}
}
Một bảng comments có thể phục vụ nhiều Model.
morphTo()
Trong model Comment:
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
Laravel sẽ tự xác định Comment thuộc Post hay Video.
Lấy Comment của Post
$post = Post::find(1);
foreach ($post->comments as $comment) {
echo $comment->body;
}
Xác định Comment thuộc Model nào
$comment = Comment::find(1);
$item = $comment->commentable;
Nếu Comment thuộc Post:
echo $item->title;
Nếu thuộc Video:
echo $item->title;
Bạn không cần kiểm tra thủ công.
Tạo Comment
$post = Post::find(1);
$post->comments()->create([
'body' => 'Bài viết rất hay!'
]);
Laravel sẽ tự lưu:
commentable_id = 1
commentable_type = App\Models\Post
Một ví dụ thực tế
Ngoài Comment, Polymorphic còn được dùng cho:
Post
Video
Product
Course
│
▼
Images
Một bảng images có thể lưu hình ảnh cho nhiều Model.
Hoặc:
Post
Video
Product
│
▼
Likes
Hay:
Post
Video
Product
Course
│
▼
Attachments
Đây đều là các ứng dụng phổ biến của Polymorphic Relationship.
Ưu điểm
Polymorphic Relationship giúp:
Giảm số lượng bảng.
Tránh trùng lặp dữ liệu.
Dễ mở rộng hệ thống.
Không cần tạo nhiều bảng giống nhau.
Đây là lý do tính năng này được sử dụng trong rất nhiều hệ thống CMS và mạng xã hội.
Tổng kết
Trong bài này chúng ta đã học:
Polymorphic Relationship là gì.
morphs().morphMany().morphTo().Chia sẻ một bảng cho nhiều Model.
Tạo và truy cập dữ liệu bằng Polymorphic.
Đây là Relationship nâng cao nhưng rất mạnh mẽ của Eloquent ORM, đặc biệt hữu ích trong các ứng dụng có nhiều loại đối tượng cùng sử dụng chung dữ liệu như bình luận, hình ảnh hoặc tệp đính kèm.
Bài tập
Tạo model
Comment.Tạo bảng
commentssử dụng$table->morphs('commentable').Khai báo
morphMany()trong modelPost.Khai báo
morphMany()trong modelVideo.Khai báo
morphTo()trong modelComment.Tạo một Comment cho Post.
Hiển thị tất cả Comment của một Video.
Kết thúc phần Relationship
Đến đây, bạn đã hoàn thành toàn bộ các Relationship quan trọng trong Eloquent ORM:
One To One
One To Many
Many To Many
Has Many Through
Polymorphic Relationship
Đây là nền tảng để xây dựng hầu hết các ứng dụng Laravel hiện đại như Blog, CMS, hệ thống bán hàng, LMS, ERP và REST API.
Bài tiếp theo
Ở Bài 18, chúng ta sẽ chuyển sang Phần 5 — FORM với chủ đề Request, tìm hiểu cách Laravel tiếp nhận và xử lý dữ liệu từ biểu mẫu (Form), URL và các yêu cầu HTTP trước khi thực hiện kiểm tra dữ liệu (Validation).
x0




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