Tìm hiểu về các Relationships trong Laravel

Tram Ho

Trong cuộc sống, mọi sự vật đều liên kết với nhau, ví dụ như một cuốn sách phải có tác giả, hay một ngôi trường phải có nhiều lớp học. Ở trong cơ sở dữ liệu cũng vậy, các bảng cũng có thể liên kết với nhau. Ở trong Laravel đã cung cấp sẵn cho chúng ta các mối quan hệ để có thể giảm thiếu thời gian công sức của các lập trình viên. Nó giúp chúng ta truy vấn các bảng trở nên dễ dàng hơn. Ở bài này chúng ta cùng nhau tìm hiểu về các loại quan hệ

  • One to One
  • One to Many
  • Many to Many
  • Has One Through
  • Has Many Through
  • Polymorphic Relations

Các mối quan hệ trong Laravel

1. One to One

Đây là một kiểu quan hệ đơn giản nhất, mà chúng ta có thể hiểu rằng cái này chỉ phụ thuộc vào cái kia và ngược lại. Ví dụ cho dễ hình dung, ta có bảng Users và bảng Avatar thì ở đây một người dùng thì chỉ có một cái avatar và chiếc avatar này chỉ đại diện cho user đó. Để biểu diễn mối quan hệ này ta sử dụng method hasOne

Ở trên ta thấy tham số truyền vào đầu tiên trong method hasOne là tên của model liên quan đến với bảng đó. Khi ta khai báo như vậy, nếu muốn lấy avatar của user có id là 1 chả hạn, ta đơn giản chỉ làm như thế này.

Chú ý ở trên Eloquent sẽ tự động match cột khóa ngoại có tên user_id của bảng Avatar tương ứng với trường id của bảng User, nếu trong trường hợp khóa ngoại không đặt là user_id mà đặt một tên khác thì cần truyền thêm một tham số thứ 2.

Tương tự với trường hợp nếu khóa chính của bảng mà bạn liên kết, bạn không đặt là id thì cần truyền tiếp một tham số thứ 3 để cho nó hiểu được là khóa ngoại của cột này tương ứng với khóa chính với cột kia

Inverse

Ở ví dụ trước thì ta có thể từ một user để gọi tới avatar tương ứng của user đó, giờ chúng ta cũng sẽ có thể truy vấn tương tự từ avatar này để truy vấn ra user thuộc về nó.

Ở ví dụ trên, Eloquent đã tự động match cột user_id ở bảng Avatar với cột id của bảng User. Trong Eloquent mặc định xác nhận khóa ngoại là tên bảng bỏ ‘s’ _id, ở trong trường hợp này là user_id. Nếu khóa ngoại ở bạng Avatar không đặt đúng theo qui chuẩn trước đó thì sẽ cần phải khai báo thêm 1 tham số thứ 2 nữa.

Nếu như bạn không muốn map foreign key của bảng Avatar với cột id ở bảng User mà lại là 1 cột khác chả hạn thì tiếp tục thêm 1 tham số thứ 3 như sau.

2. One to Many

Mối quan hệ này để biểu thị một mối quan hệ cha-con. Ví dụ một user thì sẽ có nhiều bài posts. Thì mối quan hệ này sẽ được biểu diễn như sau.

Cũng tương tự quan hệ One-One Eloquent sẽ tự động tìm khóa ngoại ở model Post , ở trong trường hợp này eloquent sẽ tìm tới khóa ngoại là “snake case” tên model _id, ở ví dụ trên sẽ là user_id, Eloquent sẽ giả định user_id là khóa ngoại ở model Post. Để truy vấn tới nhiều posts thuộc một user quá đơn giản bằng cách:

và ngược lại

3. Many to Many

Quan hệ này thì nó sẽ phức tạp hơn với hai quan hệ trước nó. Ví dụ một product sẽ thuộc nhiều orders mà một order lại có nhiều products . Để biểu diễn được quan hệ này chúng ta cần sử dụng đến một bảng thế 3, mình sẽ đặt tên là order_product.
và đồng thời sẽ chứa 2 cột là order_idproduct_id. Ở mối quan hệ này ta sẽ sử dụng method belongsToMany. Ví dụ biểu diễn method Product với bảng order

bây giờ muốn lấy ra được một product có bao nhiêu order thì chỉ cần

Có một chú ý là, Eloquent sẽ tự động tìm đến bảng trung gian đặt tên theo thứ tự alphabet, trong trường hợp này bảng sẽ tên là order_product. Tuy nhiên nếu bạn muốn đặt 1 cái tên khác mà không theo quy ước ví dụ là product_order thì chỉ cần truyền thêm tham số thứ 2 vào method belongsToMany.

Tương tự bạn cũng có thể custom lại tên của 2 tên của cột liên kết tương ứng với tham số thứ 3 và thứ 4 của method belongsToMany.
Với tham số thứ 3 sẽ là khóa ngoại của bảng đang định nghĩa quan hệ và tham số thứ 4 là bảng chúng ta muốn join. Ví dụ trong trường hợp này.

Ngược lại, đối với bảng Order ta định nghĩa như sau:

và chúng ta cũng tương tự như định nghĩa model Product, chúng ta cũng có thể truyền các tham số vào nếu muốn

Lấy giá trị của bảng trung gian
Để làm việc với mối quan hệ Many to Many này thì chúng ta cần sử dụng đến một bảng trung gian. Eloquent cũng hỗ trợ giúp chúng ta lấy được các giá trị của bảng này. Để truy cập đến các cột của bảng trung gian chúng ta sẽ sử dụng thuộc tính pivot. Ví dụ :

Theo mặc định thì Eloquent chỉ lấy các trường trung gian và created_at, update_at nếu chúng ta muốn lấy ra giá trị của một cột khác thì cần khai báo thêm như sau, giả sử chúng ta cần lấy thêm trường address

Hoặc là khi bạn muốn hai trường created_atupdate_at của bảng trung gian tự động cập nhật giá trị thì khai báo thêm

Đôi khi người dùng lại muốn thay đổi tên của thuôc tính pivot thì phải làm như thế nào, chỉ cần sử dụng method as được khai báo trong model là xong. Ví dụ

giờ muốn truy cập các thuộc tính của bảng trung gian thay thế pivot thành newname là được.

Một câu hỏi nữa được đặt ra là nếu muốn lấy các sản phẩm với điều kiện của bảng trung gian là hợp lệ thì sẽ như thế nào, rất đơn giản, Laravel cũng hỗ trợ chúng ta trong vấn đề này.

Ở đây sẽ lấy ra các Order có giá lớn hơn 20000.

4. 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:

Mặc dù bảng history không chứ supplier_id nhưng chúng ta vẫn có thể truy cập đến user's history bới mối quan hệ hasOneThrough như sau

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. Chúng ta cũng có thể custom các key liên quan đến mối quan hệ này lần lượt là các tham số sau vào hàm định nghĩa quan hệ.

hai bảng userhistory chúng ta định nghia như bình thường

5. Has Many Through

Mối quan hệ has many through nà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. Ví dụ một Team có nhiều bài Post thông qua bảng trung gian là User.

Mặc dù bảng posts không chứa khóa ngoại team_id, nhưng với quan hệ hasManyThrough sẽ cung cấp cho chúng ta lấy tất cả posts của một teams bằng cách $team->posts. Để thực hiện việc này thì Eloquent sẽ kiểm tra team_id thông qua bảng users. Chúng ta sẽ biểu diễn quan hệ như sau:

Tham số đầu tiên của quan hệ này là tên model mà chúng ta muốn truy cập, tham số thứ hai là model trung gian. Chúng ta cũng có thể custom lại tên của các khóa ngoại bằng cách thêm các tham số, với tham số thứ 3 là khóa ngoại của bảng trung gian, tham số thứ 4 là khóa ngoại của bảng mà chúng ta muốn gọi tới, tham số thứ 5 là trường mà chúng ta muốn liên kết ở bảng đang sử dụng, tham số thứ 6 là trường mà chúng ta muốn liên kết ở bảng trung gian.

6. Polymorphic

Đây là mối quan hệ đa hình trong Laravel cho phép 1 Model có thể belongsTo nhiều Model khác mà chỉ cần dùng 1 associate.

6.1 One to One Polymorphic

Mối quan hệ này tương tự quan hệ One to One, tuy nhiên 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 post có một image và một product cũng có một image, nếu như bình thường thì các bạn phải tạo thêm 2 bảng là post_image để lưu ảnh của postproduct_iamge để lưu ảnh của product, nếu có ti tỉ các bảng cần đến image thì lại phải tạo thêm bấy nhiêu bảng để lưu ảnh, vậy thì sẽ quá phức tạp và rối, vậy nên mới sinh ra mối quan hệ polymorphic này. Ví dụ :

Đây là cách để xây dựng mối quan hệ polymorphic này. Với imageable_id sẽ lưu id của bảng posts và bảng products, còn trường imageable_type sẽ lưu tên class model PostProduct. Theo convention của laravel thì bảng lưu trung gian sẽ bắt buộc phải có 2 trường idtype nhưng để rõ ràng hơn thì sẽ lưu thêm tiền tố tên_bảng_bỏ_s +able_.
Cấu trúc model

Để lấy ra image thuộc bài posts thì sẽ trỏ tới image là được.

và ngược lại từ image có thể suy ngược lại post hay product phụ thuộc vào nó.

6.1 One to Many Polymorphic

Mối quan hệ này cũng gần giống với quan hệ One to Many. Ví dụ một User có thể comment ở cả Post lẫn Video thì chỉ cần 1 bảng comments trong trường hợp này

Cấu trúc model

Lấy ra các giá trị tất cả các comment của post ta làm như sau

hay là từ comment để lấy ngược lại cái post hay videos thuộc về nó

6.1 Many to Many Polymorphic

Quan hệ này sẽ phức tạp hơn một chút. Ví dụ một post hay là video có thể có nhiều tags. Sử dụng mối quan hệ many to many polymorphic cho phép bạn truy vấn lấy ra các tags thuộc về một post hay video

Cấu trúc model

Ok bây giờ 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.

hoặc là ngược lại

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo