使用情境:一對一的關係
例如,從Score中取得某位student的分數:
scores
id | score | student_id |
---|---|---|
1 | 92 | 2 |
2 | 82 | 3 |
3 | 77 | 1 |
4 | 100 | 4 |
hasOne('related', 'foreignKey', 'localKey');
若只有給第一個參數,則預設會從第一個參數的model中找該model的id。
假如學生的id在scores這張表中的欄位名稱為'stuID',那麼第二個參數要加入'studID'
hasOne(Score::class, 'stuID')
Model Student
function score(){
return $this->hasOne(Score::class); //預設會去找scores.student_id
}
$studentWithScore = Student::with('score')->find($student_id);
使用情境:一對一或一對多的關係
例如,一間餐廳只會有一位業者,要從Restaurant中取得該餐廳的業者資料:
restaurants
id | name | owner_id |
---|---|---|
1 | Steak House | 2 |
2 | Salt&Pepper | 3 |
3 | Pastar | 2 |
belongsTo('related', 'foreignKey', 'localKey');
Model Restaurant
public function owner()
{
return $this->belongsTo(Owner::class); //預設會去找restaurants.owner_id
}
$restaurantWithOwner = Restaurant::with('owner')->find($restaurant_id);
hasMany('related', 'foreignKey', 'localKey');
使用情境:一對多的關係
例如,一間餐廳有許多食物,要從Restaurant中取得該餐廳中的所有食物:
foods
id | name | restaurant_id |
---|---|---|
1 | cake | 2 |
2 | banana | 3 |
3 | fired rice | 2 |
public function foods()
{
return $this->hasMany(Food::class); //預設會去找foods.restaurant_id,再根據foods.id找到關聯的food資料
}
$restaurantWithFoods = Restaurant::with('foods')->find($restaurant_id);
belongsToMany('related', 'table', 'foreignPivotKey', 'relatedPivotKey')
belongsToMany('和該model關聯的model類', 'pivot的表名', '該model在pivot表中的對應id', '與該model關聯的model在pivot表中的對應id')
情境一:user 訂閱 channel,一個user可以訂閱很多channels,一個channel也可以被很多個users訂閱
pivot:subscriptions 定義user和channel間的關係
id | user_id | channel_id |
---|---|---|
1 | 1 | 2 |
2 | 1 | 3 |
3 | 2 | 1 |
4 | 2 | 2 |
Model User
public function subscriptChannel()
{
return $this->belongsToMany(Channel::class, 'subscriptions', 'user_id' ,'channel_id'); //會去subscriptions中找跟user_id對應到的channel_id,再根據channel_id找到關聯的channel資料
}
Model Channel
public function subscriptUser()
{
return $this->belongsToMany(User::class, 'subscriptions', 'channel_id', 'user_id');
}
另外,可以在Model下定義關聯的function時,同時把該表所關聯的另一張表的資料也拉出來,
例如:
Model Student
function score()
{
return $this->hasOne(Score::class)->with('subject');
}
當你試圖用with()拿到關聯的資料時,報出下面這樣的錯誤訊息:
Call to a member function addEagerConstraints() on null
可能在Model的關聯function忘了加return
function user()
{
return $this->hasMany(User::class);
}
使用hasMany的function name應該要是複數的table名稱;
例如
public function foods()
{
return $this->hasMany(Food::class);
}
而使用hasOne或belongsTo的function name應該要是單數的table名稱;
範例
function score()
{
return $this->hasOne(Score::class);
}
public function owner()
{
return $this->belongsTo(Owner::class);
}
若不依照上述的規則命名,在使用ORM去找Model所關聯的表時,會找不到東西。
子查詢可以幫助我們根據表1關聯的表2的欄位來進行資料的篩選。
例如,假設scores這張表存了每位學生的國文和數學成績:student_id、math、chinse三個欄位
目標示要找出國文成績大於70,同時數學成績大於80的同學
SQL原生指令:
select * from students where exists(select * from scores where (math > 80 and chinese > 70) and student_id = students.id );
Laravel ORM:
Student::whereHas('scores', function ($query) {
$query
->where('math', '>=', 80)
->where('chinese', '>=', 70);
})->get();