Tìm kiếm bài viết

Eloquent: relationships trong laravel - Phần 1

21.09.2020

5.0/5 (1 Reviews)

Ví dụ bạn đang thiết kế web về bán hàng và dữ liệu có mỗi quan hệ phức tạp, khi đó ta cần biết về Quan hệ đa hình cho phép 1 model thuộc về nhiều hơn 1 model khác

    Polymorphic Relations là gì

    Ví dụ bạn đang thiết kế web về bán hàng và dữ liệu có mỗi quan hệ phức tạp, khi đó ta cần biết về Quan hệ đa hình cho phép 1 model thuộc về nhiều hơn 1 model khác. Ví dụ, hãy tưởng tượng users của ứng dụng của bạn có thể "comments" cả post và video. Sử dụng các mối quan hệ đa hình, bạn có thể sử dụng 1 bảng comments duy nhất cho cả 2. Trước tiên, hãy kiểm tra các cấu trúc bảng cần thiết để xây dựng mối quan hệ này.

    Cấu trúc bảng

    posts
        id - integer
        title - string
        body - text
    
    videos
        id - integer
        title - string
        url - string
    
    comments
        id - integer
        body - text
        commentable_id - integer
        commentable_type - string
    

    Hai cột quan trọng cần lưu ý là cột commentable_idcommentable_type trong bảng comments. Cột commentable_id sẽ chứa giá trị id của post hoặc video. Trong khi cột commentable_type sẽ chứa tên lớp của model sở hữu. Cột commentable_type là cách ORM xác định "type" của model sở hữu sẽ trả về khi truy cập vào các mối quan hệ commentable.

    Model Structure

    Tiếp theo, hãy kiểm tra các định nghĩa model cần thiết để xây dựng mối quan hệ này:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Comment extends Model
    {
        /**
         * Get all of the owning commentable models.
         */
        public function commentable()
        {
            return $this->morphTo();
        }
    }
    
    class Post extends Model
    {
        /**
         * Get all of the post's comments.
         */
        public function comments()
        {
            return $this->morphMany('App\Comment', 'commentable');
        }
    }
    
    class Video extends Model
    {
        /**
         * Get all of the video's comments.
         */
        public function comments()
        {
            return $this->morphMany('App\Comment', 'commentable');
        }
    }
    

    Retrieving Polymorphic Relations

    Mỗi khi bảng cơ sở dữ liệu và model của bạn được xác định, bạn có thể truy cập vào các mối quan hệ thông qua model của bạn. Ví dụ, để truy cập vào tất cả các comments cho một post, chúng ta có thể đơn giản sử dụng những property động:

    $post = App\Post::find(1);
    
    foreach ($post->comments as $comment) {
        //
    }
    

    Bạn cũng có thể truy xuất các chủ sở hữu của một mối quan hệ đa hình từ model đa hình bằng cách truy cập vào tên của method thực hiện gọi đến method morphTo. Trong trường hợp của chúng ta, đó là method commentable trên Comment model. Vì vậy, chúng ta sẽ tiếp cận phương pháp đó như là một property động:

    $comment = App\Comment::find(1);
    
    $commentable = $comment->commentable;
    

    Các mối quan hệ commentable trên mô Comment model sẽ trả lại hoặc là một Post hay dụ Video instance, tùy thuộc vào loại mô hình sở hữu các comment.

    Custom Polymorphic Types

    Theo mặc định, Laravel sẽ sử dụng tên lớp đầy đủ để lưu trữ các loại model có liên quan. Ví dụ, với các ví dụ ở trên, nơi một comment có thể thuộc về một Post hoặc một Video, commentable_type mặc định sẽ là một trong hai App\Post hoặc App\Video tương ứng. Tuy nhiên, bạn có thể muốn tách cơ sở dữ liệu của bạn từ cấu trúc bên trong của ứng dụng của bạn. Trong trường hợp đó, bạn có thể xác định một mối quan hệ "morph map" để hướng dẫn Eloquent để sử dụng một tên tùy chỉnh cho mỗi model thay vì tên lớp:

    use Illuminate\Database\Eloquent\Relations\Relation;
    
    Relation::morphMap([
        'posts' => App\Post::class,
        'videos' => App\Video::class,
    ]);
    

    Bạn có thể đăng ký morphMap trong các boot function của AppServiceProvider của bạn hoặc tạo ra một service provider riêng biệt nếu bạn muốn.

    Many To Many Polymorphic Relations

    Ngoài mối quan hệ đa hình truyền thống, bạn cũng có thể định nghĩa "many-to-many" mối quan hệ đa hình. Ví dụ, một blog PostVideo model có thể chia sẻ một mối quan hệ đa hình cho một Tag model. Sử dụng một mối quan hệ đa hình many-to-many cho phép bạn có một danh sách duy nhất của unique tags được chia sẻ trên các blog posts và videos. Trước tiên, hãy kiểm tra cấu trúc bảng:

    Table Structure

    posts
        id - integer
        name - string
    
    videos
        id - integer
        name - string
    
    tags
        id - integer
        name - string
    
    taggables
        tag_id - integer
        taggable_id - integer
        taggable_type - string
    

    Model Structure

    Tiếp theo, chúng ta đã sẵn sàng để xác định các mối quan hệ trên model. Các Post model và Video model cả hai sẽ có một tags method gọi phương thức morphToMany trên lớp base Eloquent:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model
    {
        /**
         * Get all of the tags for the post.
         */
        public function tags()
        {
            return $this->morphToMany('App\Tag', 'taggable');
        }
    }
    

    Defining The Inverse Of The Relationship

    Tiếp theo, trên Tag model, bạn nên xác định một method cho mỗi model có liên quan của nó. Vì vậy, trong ví dụ này, chúng tôi sẽ xác định một posts method và video method:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Tag extends Model
    {
        /**
         * Get all of the posts that are assigned this tag.
         */
        public function posts()
        {
            return $this->morphedByMany('App\Post', 'taggable');
        }
    
        /**
         * Get all of the videos that are assigned this tag.
         */
        public function videos()
        {
            return $this->morphedByMany('App\Video', 'taggable');
        }
    }
    

    Retrieving The Relationship

    Khi bảng cơ sở dữ liệu và model của bạn được xác định, bạn có thể truy cập vào các mối quan hệ thông qua model của bạn. Ví dụ, để truy cập vào tất cả các tags cho một post, bạn chỉ có thể sử dụng các tags property động:

    $post = App\Post::find(1);
    
    foreach ($post->tags as $tag) {
        //
    }
    

    Bạn cũng có thể truy xuất các chủ sở hữu của một mối quan hệ đa hình từ model đa hình bằng cách truy cập vào tên của phương thức đó thực hiện các cuộc gọi đến morphedByMany. Trong trường hợp của chúng ta, đó là những posts hoặc videos method trên Tag model. Vì vậy, bạn sẽ truy cập vào các method đó là property động:

    $tag = App\Tag::find(1);
    
    foreach ($tag->videos as $video) {
        //
    }
    

    Vậy là mình đã giới thiệu cho các bạn về các mối quan hệ trong Eloquent. Ở phần tiếp theo, mình sẽ tiếp tục giới thiệu cho các bạn về Querying Relations, Eager LoadingInserting & Updating Related Models.

    CÓ THỂ BẠN QUAN TÂM

    Bài Viết Cùng Chuyên Mục

    XEM THÊM
    thumbnail

    Kubernetes bài 6 - Vận hành k8s Day-Two Operations và Quản trị bằng GitOps

    22.05.2026

    Khi cụm Kubernetes của bạn đã được bảo mật cấu hình, tối ưu tài nguyên và thiết lập tự phục hồi, câu hỏi đặt ra là làm sao để duy trì sự ổn định đó trong nhiều năm tiếp theo mà không bị phụ thuộc

    thumbnail

    Kubernetes bài 5 - bảo mật Cloud Native và chuẩn DevSecOps cho K8s

    22.05.2026

    Việc siết chặt an ninh (Hardening) không phải là cấu hình một vài thông số rồi bỏ đó, mà là một tư duy phòng thủ chiều sâu.

    thumbnail

    Kubernetes bài 4 - Tối ưu Resource Auto-Healing và Scale Zero-Downtime

    22.05.2026

    Bài viết này sẽ đi sâu vào các cơ chế ở tầng Kernel giúp hệ thống tự phục hồi, chống lại các đợt tấn công cạn kiệt tài nguyên và cập nhật phiên bản mới mà người dùng không hề hay biết.

    thumbnail

    Kubernetes bài 3 - Bảo mật cấu hình k8s và config Security trên Production

    22.05.2026

    Kubernetes giải quyết bài toán này bằng hai đối tượng chuyên biệt nhưng nếu không hiểu rõ bản chất bảo mật ở tầng dưới, bạn đang tự tay dâng toàn bộ chìa khóa hệ thống cho hacker.

    thumbnail

    Kubernetes bài 2 - Mạng lưới k8s và luồng Traffic ở Packet Level

    22.05.2026

    Pod không chỉ là một container: Rất nhiều người nhầm lẫn Pod 1-1 với Container. Thực chất, Pod là đơn vị triển khai nhỏ nhất, có thể chứa một hoặc nhiều container

    Mục lục bài viết