關(guān)聯(lián)預(yù)載入
關(guān)聯(lián)預(yù)載入
版本 | 功能調(diào)整 |
---|---|
5.0.7 | 嵌套關(guān)聯(lián)支持?jǐn)?shù)組方式定義 |
5.0.5 | 增加延遲關(guān)聯(lián)預(yù)載入 |
5.0.5 | 一對一關(guān)聯(lián)預(yù)載入默認(rèn)采用IN查詢方式 |
5.0.4 | 一對一關(guān)聯(lián)支持JOIN和IN兩種方式預(yù)載入查詢 |
關(guān)聯(lián)查詢的預(yù)查詢載入功能,主要解決了N+1
次查詢的問題,例如下面的查詢?nèi)绻?個記錄,會執(zhí)行4次查詢:
$list = User::all([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的profile模型數(shù)據(jù)
dump($user->profile);
}
如果使用關(guān)聯(lián)預(yù)查詢功能,對于一對一關(guān)聯(lián)來說,只有一次查詢,對于一對多關(guān)聯(lián)的話,就可以變成2次查詢,有效提高性能。
$list = User::with('profile')->select([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的profile模型數(shù)據(jù)
dump($user->profile);
}
支持預(yù)載入多個關(guān)聯(lián),例如:
$list = User::with('profile,book')->select([1,2,3]);
也可以支持嵌套預(yù)載入,例如:
$list = User::with('profile.phone')->select([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的phone模型
dump($user->profile->phone);
}
V5.0.7
版本以上,支持使用數(shù)組方式定義嵌套預(yù)載入,例如下面的預(yù)載入要同時獲取用戶的Profile
關(guān)聯(lián)模型的Phone
、Job
和Img
子關(guān)聯(lián)模型數(shù)據(jù):
$list = User::with(['profile'=>['phone','job','img']])->select([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)
dump($user->profile->phone);
dump($user->profile->job);
dump($user->profile->img);
}
可以在模型的get和all方法中使用預(yù)載入,和使用select方法是等效的:
$list = User::all([1,2,3],'profile,book');
如果要指定屬性查詢,可以使用:
$list = User::field('id,name')->with(['profile'=>function($query){$query->field('email,phone');}])->select([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的profile模型數(shù)據(jù)
dump($user->profile);
}
關(guān)聯(lián)預(yù)載入名稱是關(guān)聯(lián)方法名,從V5.0.4+
版本開始,支持傳入方法名的小寫和下劃線定義方式,例如如果關(guān)聯(lián)方法名是userProfile
和userBook
的話:
$list = User::with('userProfile,userBook')->select([1,2,3]);
等效于:
$list = User::with('user_profile,user_book')->select([1,2,3]);
V5.0.4+
版本開始一對一關(guān)聯(lián)預(yù)載入支持兩種方式:JOIN
方式(一次查詢)和IN
方式(兩次查詢),如果要使用IN
方式關(guān)聯(lián)預(yù)載入,在關(guān)聯(lián)定義方法中添加
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
public function profile()
{
// 設(shè)置預(yù)載入查詢方式為IN方式
return $this->hasOne('Profile')->setEagerlyType(1);
}
}
V5.0.5+
版本開始,默認(rèn)使用IN查詢方式,如果需要改為JOIN查詢方式,使用
// 設(shè)置預(yù)載入查詢方式為JOIN方式
return $this->hasOne('Profile')->setEagerlyType(0);
延遲預(yù)載入(V5.0.5+
)
有些情況下,需要根據(jù)查詢出來的數(shù)據(jù)來決定是否需要使用關(guān)聯(lián)預(yù)載入,當(dāng)然關(guān)聯(lián)查詢本身就能解決這個問題,因為關(guān)聯(lián)查詢是惰性的,不過用預(yù)載入的理由也很明顯,性能具有優(yōu)勢。
延遲預(yù)載入僅針對多個數(shù)據(jù)的查詢,因為單個數(shù)據(jù)的查詢用延遲預(yù)載入和關(guān)聯(lián)惰性查詢沒有任何區(qū)別,所以不需要使用延遲預(yù)載入。
如果你的數(shù)據(jù)集查詢返回的是數(shù)據(jù)集對象,可以使用調(diào)用數(shù)據(jù)集對象的load
實現(xiàn)延遲預(yù)載入:
// 查詢數(shù)據(jù)集
$list = User::all([1,2,3]);
// 延遲預(yù)載入
$list->load('cards');
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的card模型數(shù)據(jù)
dump($user->cards);
}
如果你的數(shù)據(jù)集查詢返回的是數(shù)組,系統(tǒng)提供了一個load_relation
助手函數(shù)可以完成同樣的功能。
// 查詢數(shù)據(jù)集
$list = User::all([1,2,3]);
// 延遲預(yù)載入
$list = load_relation($list,'cards');
foreach($list as $user){
// 獲取用戶關(guān)聯(lián)的card模型數(shù)據(jù)
dump($user->cards);
}