Nếu các bạn đã học về cơ sở dữ liệu thì hẳn mọi người đều biết giữa các bảng có liên kết với nhau. Ở trong Laravel chũng cung cấp cho chúng các Relationships giúp việc truy vấn trở nên dễ dàng hơn.
1. One to One
- Đây là kiểu quan hệ đơn giản nhất, nó thể hiện cho việc 
một người có một thứ và thứ đó chỉ thuộc về người này. - Như bạn có bảng 
usersvà bảngphonesthì mộtusercó 1 cái điện thoại vàphoneđó chỉ thuộc vềuserđó. - Trong 
laravelđể tạo quan hệ cho 2 model có quan hệOne to Oneta sử dụng phương thứchasOne. 
<?phpnamespaceAppModels;useIlluminateDatabaseEloquentModel;classUserextendsModel{/**
     * Get the phone associated with the user.
     */publicfunctionphone(){return$this->hasOne(Phone::class);}}
- Sau khi tạo 
quan hệxong ta có thể truy vấn tớiphonemà cóusercó tên làNguyen Van Anhư sau: 
User::where('name','Nguyen Van A')->phone;
- Ngoài ra bạn cũng có thể định nghĩa khóa ngoại cho quan hệ này bằng cách thêm tham số thứ 2:
 
return$this->hasOne(Phone::class,'foreign_key');
- Ngược lại đối với model 
Phoneta sử dụng phương thứcbelongsTođể định nghĩaInversevới modelUser: 
<?phpnamespaceAppModels;useIlluminateDatabaseEloquentModel;classPhoneextendsModel{/**
     * Get the user that owns the phone.
     */publicfunctionuser(){return$this->belongsTo(User::class);}}
- Giống với  model 
Userbạn cũng có thể định nghĩa khóa ngoại bằng cách thêm tham số thứ 2 và tất nhiên là bạn cũng có thể truy vấn tớiusertương ứng. 
2. One to Many
- Quan hệ này biểu thị cho mối quan hệ 
cha-con. Ví dụ như mộtusercó nhiềupostsnhưng các bàipostchỉ thuộc mộtuser. - Mối quan hệ này được biểu diễn như sau:
 
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classUserextendsAuthenticatable{publicfunctionposts(){return$this->hasMany(Post::class);}}
- Giống với quan hệ 
One to Onebạn cũng có thể thêm tham số thứ 2 để định nghĩa khóa ngoại. - Và bạn cũng phải định nghĩa 
Inversecho modelPost 
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classPostextendsModel{publicfunctionuser(){return$this->belongsTo(User::class);}}
3. Many to Many
- Quan hệ này phức tạp hơn 2 quan hệ 
One to OnevàOne to Manyví như mộtProductsẽ thuộc nhiềuOrdersvà mộtOrdercũng có nhiềuProducts. - Để biểu diễn được quan hệ này thì chúng ta phải có một bảng thứ 3 là 
product_ordervà chưa 2 trường làproduct_idvàorder_id. - Sau khi có bảng trung gian thì chúng ta định nghĩa quan hệ này thông qua phương thức 
belongsToManyở cả 2 model. 
namespaceApp;useIlluminateDatabaseEloquentModel;classProductextendsModel{publicfunctionorders(){return$this->belongsToMany(Order::class);}}
namespaceApp;useIlluminateDatabaseEloquentModel;classOrderextendsModel{publicfunctionproduct(){return$this->belongsToMany(Product::class);}}
- 
Và để định nghĩa khóa ngoại thì bạn cần thêm tham số thứ 2, thứ 3 và thứ 4.
 - 
Trong đó:
Tham số thứ 2tương ứng với bảng trung gian.Tham số thứ 3vàtham số thứ 4tương ứng với khóa ngoại của 2 bảng cần tạo quan hệ.
 
namespaceApp;useIlluminateDatabaseEloquentModel;classProductextendsModel{publicfunctionorders(){return$this->belongsToMany(Order::class,'product_order','product_id','order_id');}}
- Tất nhiên trong một số trường hợp thì bảng trung gian của bạn cũng có thể có thêm các trường khác nữa thì trong 
Laravelcung cấp cho bạn một phương thức làpivotđể lấy ra các trường đó. ví dụ: 
$product=Product::find(1);foreach($product->ordersas$order){echo$order->pivot->created_at;}
- Để có thể lấy được thì bạn cần phải định nghĩa tròng model như sau:
 
namespaceApp;useIlluminateDatabaseEloquentModel;classProductextendsModel{publicfunctionorders(){return$this->belongsToMany(Order::class)->withPivot('total_price');}}
4. Các quan hệ nâng cao
- Ngoài 3 quan hệ cơ bản ở trên thì 
laracelcó cung cấp thêm cho bạn các quan hệ nâng cao khác. 
4.1 Has One Through
- Đây là một mối quan hệ liên kết các bảng với nhau thông qua một bảng trung gian Ví dụ có 3 bảng:
 
users
    id - integer
    supplier_id - integer
suppliers
    id - integer
history
    id - integer
    user_id - integer
- Mặc dù bảng 
historykhông chứasupplier_idnhưng chúng ta vẫn có thể truy cập đến lịch sử của user đó bới mối quan hệhasOneThroughnhư sau: 
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classSupplierextendsModel{publicfunctionuserHistory(){return$this->hasOneThrough(History::class,User::class);}}
- Với tham số thứ nhất được truyền vào là tên của model mà chúng ta muốn truy cập, tham số thứ 2 là model trung gian.
 - Còn ở hai bảng 
uservàhistorychúng ta định nghĩa như bình thường. 
4.2 Has Many Through
- Mối quan hệ 
has many throughnày cung cấp cho chúng ta cách truy cập bảng liên kết dễ dàng hơn thông qua bảng trung gian. 
teams
    id - integer
    name - string
users
    id - integer
    team_id - integer
    name - string
posts
    id - integer
    user_id - integer
    title - string
- Giống như 
Has One Throughbạn cũng có thể lấy ra tất cả bàipostscủa mộtteambằng cách$team->posts. 
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classTeamextendsModel{publicfunctionposts(){return$this->hasManyThrough(Post::class,User::class);}}
4.3 One to One Polymorphic
- Mối quan hệ này tương tự quan hệ 
One to One, nhưng mục đích của mối quan hệ này là 1 model có thể belongsTo 1 hay nhiều model khác. - Ví dụ một bài 
postcó 1imagevà 1productcũng có 1imagethì bạn cần tạo thêm 2 bảng làpost_imagevàproduct_imageđể lưu ảnh cho chúng thì vớiPolymorphicthì bạn chỉ cần 1 bảngimageslà đủ: 
posts
    id - integer
    name - string
products
    id - integer
    name - string
images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string
- 
Trong đó:
imageable_idlàidcủa bảngproductshoặcposts.imageable_typechứa tên của modelAppModelsProducthoặcAppModelsPost.
 - 
Model Image:
 
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classImageextendsModel{publicfunctionimageable(){return$this->morphTo();}}
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classPostextendsModel{publicfunctionimage(){return$this->morphOne(Image::class,'imageable');}}
<?phpnamespaceApp;useIlluminateDatabaseEloquentModel;classProductextendsModel{publicfunctionimage(){return$this->morphOne(Image::class,'imageable');}}
- Để lấy ra 
image 
$post=Post::find(1);$image=$post->image;
- Bạn cũng có thể truy vấn ngược để lấy ra 
posthoặcproduct: 
$image=Image::find(1);$imageable=$image->imageable;
4.4 One to Many Polymorphic
- Quan hệ này khá giống với quan hệ 
One to One Polymorphicbạn chỉ cần thaymorphOnethànhmorphManylà được. Vì giống với cách định nghĩa ở trên nên mình sẽ không nhắc lại nữa. 
4.5 Many to Many Polymorphic
- Vì là quan hệ 
Many to Manynên bạn cũng cần tạp ra một bảng trung gian. - Ví dụ một 
posthay làvideocó thể có nhiềutags. Sử dụng mối quan hệmany to many polymorphiccho phép bạn truy vấn lấy ra cáctagsthuộc về mộtposthayvideo. 
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
- Cấu trúc model
 
//post.php<?php
namespaceApp;useIlluminateDatabaseEloquentModel;classPostextendsModel{publicfunctiontags(){return$this->morphToMany(Tag::class,'taggable');}}
classTagextendsModel{publicfunctionposts(){return$this->morphedByMany(Post::class,'taggable');}publicfunctionvideos(){return$this->morphedByMany(Video::class,'taggable');}}
- Muốn lấy ra các tag thuộc về một post ta cũng làm tương tự nhưng mối quan hệ khác.
 
$post=Post::find(1);foreach($post->tagsas$tag){//}
- hoặc là ngược lại:
 
$tag=Tag::find(1);foreach($tag->videosas$video){//}
5. Kết luận
- Bài viết này mình giói thiệu cho các bạn về 
Relationshipstrong laravel. Mong răng nó sẽ giúp ích được cho các bạn. - Link tham khảo: https://laravel.com/docs/8.x/eloquent-relationships
 
Nguồn: viblo.asia
