Những điều cần biết về relationships trong laravel (phần 1)

0
0
173

Người đăng: Kiên

Theo Viblo Asia

Hello mn, cũng lâu rồi mình không “đụng chạm” tới phần này nên bài viết này mình sẽ vừa ôn lại vừa giới thiệu cho các bạn những thứ mình biết về relationships. Chắc các bạn cũng biết rằng mỗi một PHP Framework có một cách tạo relationships model khác nhau, tuy nhiên ”background” của nó đều chỉ là những câu lệnh SQL mà thôi, tương tự với Laravel Framework. Thông qua việc define các relationships trong model, chúng ta có thể thực hiện các truy vấn dữ liệu mà không cần viết các câu SQL, điều này khiến cho việc thao tác với database trở nên dễ dàng và dễ hiểu hơn rất nhiều.

Các loại relationships

Trong 1 cơ sở tài liệu quan hệ thì những table sẽ link với nhau trải qua quan hệ :

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

Định nghĩa

Eloquent Relationships được define là những function bên trong Eloquent Model Class. Giống như những Eloquent Model, những relationships cũng tương hỗ những query builder can đảm và mạnh mẽ và cung ứng nhiều tính năng hay ho khác nữa ( mình sẽ nói tới ở phần khác nhé ). Bây giờ tất cả chúng ta sẽ cùng xem làm thế nào để xác lập từng loại relationship và dùng trong trường hợp nào .

One to One

Đây là một quan hệ rất thường thấy .

Ví dụ : ta có quan hệ sau 1 người sẽ chỉ có 1 thẻ căn cước công dân.

Chúng ta đặt một method card trong User model class để xác định mối quan hệ này :

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class User extends Model { public function phone() { return USD this->hasOne(Card::class); } }

Đối số đầu tiên truyền cho phương thức hasOne là tên của model được liên kết (nên đặt các class model trong cùng thư mục để không phải khai báo model, ở trên ta đã sử dụng Card::class mà không cần phải use App\Models\Card ). Một khi các mối quan hệ được xác định, chúng ta có thể truy xuất các bản ghi sư dụng Eloquent’s dynamic properties. Dynamic properties cho phép bạn truy cập vào các relationship functions như thể nó là thuộc tính được định nghĩa trên các model:

USD card = User::find(1)->card;

Eloquent giả định các foreign key dựa theo tên model.Trong trường hợp này, Card model sẽ tự động lấy foreign key là user_id. Nếu bạn muốn đặt tên khác cho foreign key trỏ tới bảng Users ở bảng Cards, bạn có thể thêm vào đối số thứ 2 của hasOne method:

return USD this->hasOne(Card::class, ' congdan_id ');

Ngoài ra, nếu bạn muốn dùng cột tên userId làm primary key của bảng Users, bạn có thể truyền thêm 1 đối số thứ 3 trong phương thức hasOne như sau:

return USD this->hasOne(Card::class, ' congdan_id ', ' userId '); 

Mình hay sử dụng phong cách thiết kế tiên phong, ngắn gọn và chỉ cần nhớ tên bảng .
Tiếp tục nhé, ta vừa mới define quan hệ ” 1 người có 1 thẻ căn cước công dân “, giờ đây ta sẽ định nghĩa quan hệ ” 1 thẻ căn cước thuộc về 1 công dân “, còn gọi là Inverse của Relationship .

Trong Card model ta truy cập vào User model thông qua method user. Chúng ta sử dụng phương thức nghịch đảo của hasOne là belongsTo:

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class Card extends Model { public function user() { return USD this->belongsTo(User::class); } }

Tương tự như trường hợp trên khi bạn muốn tự đặt tên khác cho foreign key hay cả primary key thì ta sẽ dùng như sau :

public function user()
{ return USD this->belongsTo(User::class, ' congdan_id ');  
}

hoặc

public function user()
{ return USD this->belongsTo(User::class, ' congdan_id ', ' userId ');  
}

One To Many

Giống như tên gọi, 1 model sẽ sở hữu nhiều model khác. Quay trở lại với ví dụ kinh điển đó là 1 bài đăng trên facebook sẽ có nhiều lượt like. Giống như nhiều Eloquent relationship khác, one-to-many được xác định bằng 1 function được đặt ở model local (mình coi model local là Post):

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class Post extends Model { public function likes() { return USD this->hasMany(Like::class); } }

Nhớ rằng, Eloquent sẽ tự động hóa xác lập đúng cột foreign key trên Like Mã Sản Phẩm. Theo quy ước, Eloquent sẽ có ” snake case ” tên của Model và hậu tố _id. Vì vậy, trong ví dụ này, Eloquent sẽ hiểu foreign key trên Like Model chính là post_id .
Một khi relationship được xác lập, tất cả chúng ta hoàn toàn có thể truy vấn lấy collection của Like Model bằng cách truy vấn lấy likes property như sau :

USD likes = Post::find(1)->likes;

Bạn hoàn toàn có thể rằng buộc

USD likes = Post::find(1)->likes()->where(' something_condition ')->first();

Giống như hasOne, bạn cũng hoàn toàn có thể ghi đè những foreign key hay local key bằng cách thêm những đối số cho phương pháp hasMany .

return USD this->hasMany(Like::class, ' foreign_key '); return USD this->hasMany(Like::class, ' foreign_key ', ' local_key ');

Tiếp tục, ta sẽ định nghĩa Inverse của quan hệ One To Many trên là ” mỗi một like thuộc về duy nhất 1 bài đăng ” :

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class Like extends Model { public function post() { return USD this->belongsTo(Post::class); } }

Bây giờ từ 1 like ta hoàn toàn có thể lấy thông tin về post chiếm hữu nó trải qua ” dynamic property ” là post :

USD like = Like::find(1); echo USD like->post;

Tương tự, bạn cũng hoàn toàn có thể ghi đè những foreign key hay local key như sau :

public function post()
{ return USD this->belongsTo(Post:

:

class, ' foreign_key '); }
public function post()
{ return USD this->belongsTo(Post::class, ' foreign_key ', ' local_key ');
}

Many To Many

Hơi phức tạp so với hasOne và hasMany. Một ví dụ cho mối quan hệ này như là 1 user sẽ có nhiều roles và 1 role cũng sẽ thuộc về nhiều user. Để xác định relationship này, cần thiết phải có 3 bảng: users, roles và user_role. Bảng user_role sẽ chứa 2 column user_id và role_id.

Quan hệ many-to-many được định nghĩa bằng cách gọi phương pháp belongsToMany dựa trên Eloquent class. Ví dụ, hãy định nghĩa phương pháp roles trên User Model .

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class User extends Model { public function roles() { return USD this->belongsToMany(Role::class); } }

Một khi những mối quan hệ được xác lập, bạn hoàn toàn có thể truy vấn vào roles bằng cách truy vấn dynamic property :

USD user = User::find(1);

Giống như toàn bộ những relationship khác, bạn hoàn toàn có thể gọi phương pháp roles và liên tục cho thêm vào những query :

USD roles = User::find(1)->roles()->orderBy(' name ')->get();

Để xác lập tên bảng của bảng tham gia vào relationship, Eloquent sẽ join 2 Mã Sản Phẩm tương quan theo thứ tự của bảng vần âm. Tuy nhiên, bạn cũng hoàn toàn có thể ghi đè quy ước này. Bạn hoàn toàn có thể làm như vậy bằng cách thêm vào 1 đối số thứ 2 trong phương pháp belongsToMany như sau :

return USD this->belongsToMany(Role::class, ' role_user ');

Ngoài tùy biến trên, bạn hoàn toàn có thể tùy biến những tên cột của những keys bằng cách truyền thêm đối số cho phương pháp belongsToMany. Đối số thứ 3 là tên foreign key mà bạn đang xác lập relationship, trong khi đối số thứ 4 là tên foreign key trong Mã Sản Phẩm mà bạn đang join đến .

return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');

Định nghĩa Inverse của quan hệ

Để xác lập những nghịch đảo của mối quan hệ many-to-many, bạn chỉ cần đặt một phương pháp belongsToMany trên Model của bạn. Chúng ta hay định nghĩa phương pháp users trên Role Mã Sản Phẩm :

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class Role extends Model { public function users() { return USD this->belongsToMany(User::class); } }

Truy xuất dữ liệu trong bảng trung gian ( ở đây là bảng user_role):

Khi làm việc với mối quan hệ many-to-many đòi hỏi cần thêm 1 bảng trung gian. Eloquent cung cấp một số cách hữu ích để tương tác với bảng này. Ví dụ, chúng ta hãy giả định đối tượng đang sử dụng của chúng ta đã có nhiều đối tượng Role. Sau khi truy cập mối quan hệ này, chúng ta có thể truy cập vào bảng trung gian bằng cách sử dụng pivot attribute trên model.

USD user = User::find(1); foreach (USD user->roles as USD role) { echo USD role->pivot->created_at;
}

Chú ý rằng, mỗi Role Mã Sản Phẩm tất cả chúng ta nhận được tự động hóa gán một pivot attribute. Thuộc tính này chứa 1 Model đại diện thay mặt cho bảng trung gian, và hoàn toàn có thể sử dụng như bất kỳ Eloquent Model nào khác. Theo mặc định, chỉ có những keys sẽ xuất hiện trên những pivot object. Nếu bảng pivot của bạn chứa những thuộc tính lan rộng ra, bạn phải xác lập chúng khi xác lập những mối quan hệ :

return USD this->belongsToMany(Role::class)->withPivot(' column1 ', ' column2 ');

Nếu bạn muốn bảng pivot của bạn tự động hóa có created_at và updated_at timestamps, sử dụng những phương pháp Timestamps vào trong định nghĩa của mối quan hệ :

return USD this->belongsToMany(Role::class)->withTimestamps();

Ta cũng hoàn toàn có thể lọc những mối quan hệ trải qua những cột bảng trung gian bởi belongsToMany bằng cách sử dụng phương pháp wherePivot and wherePivotIn khi định nghĩa những mối quan hệ :

return USD this->belongsToMany(Role::class)->wherePivot(' approved ', 1); return USD this->belongsToMany(Role::class)->wherePivotIn(' approved ', [1, 2]);

Has Many Through

Quan hệ “has-many-through” cung cấp một thuận tiện short-cut để truy cập vào các mối quan hệ xa thông qua một mối quan hệ trung gian. Ví dụ, một Country model có thể có nhiều Post model thông qua một User model trung gian. Trong ví dụ này, bạn có thể dễ dàng lấy tất cả các blog post cho 1 country. Hãy nhìn vào các bảng cần thiết để xác định mối quan hệ này:

Mặc dù post không chứa cột country_id, mối quan hệ hasManyThrough cung cấp quyền truy cập vào post của country thông qua $country->posts. Để thực hiện các truy vấn này, Eloquent kiểm tra các country_id trên bảng user trung gian. Sau khi tìm ra id của user phù hợp, chúng được sử dụng để truy vấn bảng posts. Bây giờ chúng ta đã xem xét các cấu trúc bảng cho các mối quan hệ, hãy định nghĩa nó trên Country model.

namespace

App\Models

; use

Illuminate\Database\Eloquent\Model

; class Country extends Model { public function posts() { return USD this->hasManyThrough(Post::class, User::class); } }

Đối số tiên phong truyền cho phương pháp hasManyThrough là tên của Model ở đầu cuối tất cả chúng ta muốn truy vấn, trong khi đối số thứ 2 là tên của Model trung gian. Nếu bạn muốn tùy chỉnh những foreign key của relationship, bạn hoàn toàn có thể truyền vào những đối số thứ 3 và thứ 4 của phương pháp hasManyThrough. Đối số thứ 3 là foreign key của Model trung gian, đối số thứ 4 là foreign key của Mã Sản Phẩm ở đầu cuối và đối số thứ 5 là local key .

class Country extends Model
{ public function posts() { return USD this->hasManyThrough( Post::class, User::class, ' country_id ', ' user_id ', ' id ' )

;

} }

Tạm kết

Ok, bài viết cũng khá dài rồi, mình sẽ để các relationship còn lại cho bài viết sau. Hy vọng bài viết sẽ giúp các bạn nắm được 1 số relationship cơ bản. Cám ơn mn đã quan tâm đến bài viết ?