X

Eloquent: relationships trong laravel - Phần 1

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.