W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
當然,您的數據庫表很可能跟另一張表相關聯(lián)。例如,一篇 blog 文章可能有很多評論,或是一張訂單跟下單客戶相關聯(lián)。 Eloquent 讓管理和處理這些關聯(lián)變得很容易。 Laravel 有很多種關聯(lián)類型:
一對一關聯(lián)是很基本的關聯(lián)。例如一個 User 模型會對應到一個 Phone 。 在 Eloquent 里可以像下面這樣定義關聯(lián):
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
傳到 hasOne 方法里的第一個參數是關聯(lián)模型的類名稱。定義好關聯(lián)之后,就可以使用 Eloquent 的動態(tài)屬性取得關聯(lián)對象:
$phone = User::find(1)->phone;
SQL 會執(zhí)行如下語句:
select * from users where id = 1
select * from phones where user_id = 1
注意, Eloquent 假設對應的關聯(lián)模型數據庫表里,外鍵名稱是基于模型名稱。在這個例子里,默認 Phone 模型數據庫表會以 user_id 作為外鍵。如果想要更改這個默認,可以傳入第二個參數到 hasOne 方法里。更進一步,您可以傳入第三個參數,指定關聯(lián)的外鍵要對應到本身的哪個字段:
return $this->hasOne('App\Phone', 'foreign_key');
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
要在 Phone 模型里定義相對的關聯(lián),可以使用 belongsTo 方法:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
在上面的例子里, Eloquent 默認會使用 phones 數據庫表的 user_id 字段查詢關聯(lián)。如果想要自己指定外鍵字段,可以在 belongsTo 方法里傳入第二個參數:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User', 'local_key');
}
}
除此之外,也可以傳入第三個參數指定要參照上層數據庫表的哪個字段:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User', 'local_key', 'parent_key');
}
}
一對多關聯(lián)的例子如,一篇 Blog 文章可能「有很多」評論??梢韵襁@樣定義關聯(lián):
class Post extends Model {
public function comments()
{
return $this->hasMany('App\Comment');
}
}
現在可以經由動態(tài)屬性取得文章的評論:
$comments = Post::find(1)->comments;
如果需要增加更多條件限制,可以在調用 comments 方法后面通過鏈式查詢條件方法:
$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();
同樣的,您可以傳入第二個參數到 hasMany 方法更改默認的外鍵名稱。以及,如同 hasOne 關聯(lián),可以指定本身的對應字段:
return $this->hasMany('App\Comment', 'foreign_key');
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
要在 Comment 模型定義相對應的關聯(lián),可使用 belongsTo 方法:
class Comment extends Model {
public function post()
{
return $this->belongsTo('App\Post');
}
}
多對多關聯(lián)更為復雜。這種關聯(lián)的例子如,一個用戶( user )可能用有很多身份( role ),而一種身份可能很多用戶都有。例如很多用戶都是「管理者」。多對多關聯(lián)需要用到三個數據庫表: users , roles ,和 role_user 。 role_user 樞紐表命名是以相關聯(lián)的兩個模型數據庫表,依照字母順序命名,樞紐表里面應該要有 user_id 和 role_id 字段。
可以使用 belongsToMany 方法定義多對多關系:
class User extends Model {
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
現在我們可以從 User 模型取得 roles:
$roles = User::find(1)->roles;
如果不想使用默認的樞紐數據庫表命名方式,可以傳遞數據庫表名稱作為 belongsToMany 方法的第二個參數:
return $this->belongsToMany('App\Role', 'user_roles');
也可以更改默認的關聯(lián)字段名稱:
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'foo_id');
當然,也可以在 Role 模型定義相對的關聯(lián):
class Role extends Model {
public function users()
{
return $this->belongsToMany('App\User');
}
}
「遠層一對多關聯(lián)」提供了方便簡短的方法,可以經由多層間的關聯(lián)取得遠層的關聯(lián)。例如,一個 Country 模型可能通過 Users 關聯(lián)到很多 Posts 模型。 數據庫表間的關系可能看起來如下:
countries |
---|
id - integer |
name - string |
users |
---|
id - integer |
country_id - integer |
name - string |
posts |
---|
id - integer |
user_id - integer |
title - string |
雖然 posts 數據庫表本身沒有 country_id 字段,但 hasManyThrough 方法讓我們可以使用 $country->posts 取得 country 的 posts。我們可以定義以下關聯(lián):
class Country extends Model {
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
如果想要手動指定關聯(lián)的字段名稱,可以傳入第三和第四個參數到方法里:
class Country extends Model {
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id');
}
}
多態(tài)關聯(lián)可以用一個簡單的關聯(lián)方法,就讓一個模型同時關聯(lián)多個模型。例如,您可能想讓 photo 模型同時和一個 staff 或 order 模型關聯(lián)??梢远x關聯(lián)如下:
class Photo extends Model {
public function imageable()
{
return $this->morphTo();
}
}
class Staff extends Model {
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
class Order extends Model {
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
現在我們可以從 staff 或 order 模型取得多態(tài)關聯(lián)對象:
$staff = Staff::find(1);
foreach ($staff->photos as $photo)
{
//
}
然而,多態(tài)關聯(lián)真正神奇的地方,在于要從 Photo 模型取得 staff 或 order 對象時:
$photo = Photo::find(1);
$imageable = $photo->imageable;
Photo 模型里的 imageable 關聯(lián)會返回 Staff 或 Order 實例,取決于這是哪一種模型擁有的照片。
多態(tài)關聯(lián)的數據庫表結構
為了理解多態(tài)關聯(lián)的運作機制,來看看它們的數據庫表結構:
staff |
---|
id - integer |
name - string |
orders |
---|
id - integer |
price - integer |
photos |
---|
id - integer |
path - string |
imageable_id - integer |
imageable_type - string |
要注意的重點是 photos 數據庫表的 imageable_id 和 imageable_type。在上面的例子里, ID 字段會包含 staff 或 order 的 ID,而 type 是擁有者的模型類名稱。這就是讓 ORM 在取得 imageable 關聯(lián)對象時,決定要哪一種模型對象的機制。
Polymorphic Many To Many Relation Table Structure 多態(tài)的多對多關聯(lián)數據庫表結構
除了一般的多態(tài)關聯(lián),也可以使用多對多的多態(tài)關聯(lián)。例如,Blog 的 Post 和 Video 模型可以共用多態(tài)的 Tag 關聯(lián)模型。首先,來看看數據庫表結構:
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 |
現在,我們準備好設定模型關聯(lián)了。 Post 和 Video 模型都可以經由 tags 方法建立 morphToMany 關聯(lián):
class Post extends Model {
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
}
在 Tag 模型里針對每一種關聯(lián)建立一個方法:
class Tag extends Model {
public function posts()
{
return $this->morphedByMany('App\Post', 'taggable');
}
public function videos()
{
return $this->morphedByMany('App\Video', 'taggable');
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: