關聯預載入
關聯預載入
| 版本 | 功能調整 |
|---|---|
| 5.0.7 | 嵌套關聯支持數組方式定義 |
| 5.0.5 | 增加延遲關聯預載入 |
| 5.0.5 | 一對一關聯預載入默認采用IN查詢方式 |
| 5.0.4 | 一對一關聯支持JOIN和IN兩種方式預載入查詢 |
關聯查詢的預查詢載入功能,主要解決了N+1次查詢(xun)(xun)的問題,例如下面(mian)的查詢(xun)(xun)如果有3個記錄,會執行4次查詢(xun)(xun):
$list = User::all([1,2,3]);
foreach($list as $user){
// 獲取用戶關聯(lian)的profile模型數據(ju)
dump($user->profile);
}
如果使(shi)用關(guan)聯(lian)預查詢功能,對于一對一關(guan)聯(lian)來說,只有一次(ci)查詢,對于一對多關(guan)聯(lian)的話,就(jiu)可以變(bian)成(cheng)2次(ci)查詢,有效提高(gao)性能。
$list = User::with('profile')->select([1,2,3]);
foreach($list as $user){
// 獲取用戶(hu)關(guan)聯的profile模型數據
dump($user->profile);
}
支持預載(zai)入多個關聯,例如:
$list = User::with('profile,book')->select([1,2,3]);
也可以支持(chi)嵌套(tao)預載入,例如:
$list = User::with('profile.phone')->select([1,2,3]);
foreach($list as $user){
// 獲取用戶關(guan)聯的phone模型
dump($user->profile->phone);
}
V5.0.7版本以上,支持使用數組方式定義嵌套預載入,例如下面的預載入要同時獲取用戶的Profile關聯模型的Phone、Job和Img子關聯模型數據:
$list = User::with(['profile'=>['phone','job','img']])->select([1,2,3]);
foreach($list as $user){
// 獲取用戶(hu)關(guan)聯
dump($user->profile->phone);
dump($user->profile->job);
dump($user->profile->img);
}
可以在模型的(de)get和(he)all方法中使(shi)用預載(zai)入(ru),和(he)使(shi)用select方法是等(deng)效(xiao)的(de):
$list = User::all([1,2,3],'profile,book');
如果要指(zhi)定屬性查詢(xun),可(ke)以使用:
$list = User::field('id,name')->with(['profile'=>function($query){$query->field('email,phone');}])->select([1,2,3]);
foreach($list as $user){
// 獲取用戶(hu)關聯的profile模(mo)型(xing)數據
dump($user->profile);
}
關聯預載入名稱是關聯方法名,從V5.0.4+版本開始,支持傳入方法名的小寫和下劃線定義方式,例如如果關聯方法名是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+版本開始一對一關聯預載入支持兩種方式:JOIN方式(一次查詢)和IN方式(兩次查詢),如果要使用IN方式關聯(lian)預載入,在關聯(lian)定義(yi)方法(fa)中添(tian)加
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
public function profile()
{
// 設(she)置(zhi)預載入(ru)查詢方(fang)式為IN方(fang)式
return $this->hasOne('Profile')->setEagerlyType(1);
}
}
V5.0.5+版本(ben)開始,默認使用IN查詢方式,如(ru)果需要改為(wei)JOIN查詢方式,使用
// 設(she)置預(yu)載入查詢方式為JOIN方式
return $this->hasOne('Profile')->setEagerlyType(0);
延遲預載入(V5.0.5+)
有(you)些(xie)情況下,需(xu)要根據查詢(xun)出來(lai)的數據來(lai)決定是否需(xu)要使用(yong)關聯預載(zai)入,當然(ran)關聯查詢(xun)本(ben)身就能(neng)(neng)解決這個問(wen)題,因為關聯查詢(xun)是惰(duo)性的,不過用(yong)預載(zai)入的理由也很明顯,性能(neng)(neng)具有(you)優勢。
延遲(chi)預載(zai)(zai)入僅針(zhen)對(dui)多(duo)個(ge)數據(ju)的查(cha)詢,因(yin)為(wei)單(dan)個(ge)數據(ju)的查(cha)詢用延遲(chi)預載(zai)(zai)入和關聯惰性查(cha)詢沒(mei)有任何區(qu)別,所以不需要使用延遲(chi)預載(zai)(zai)入。
如果你的數據集查詢返回的是數據集對象,可以使用調用數據集對象的load實現延遲預載入:
// 查(cha)詢數據集
$list = User::all([1,2,3]);
// 延遲預載入
$list->load('cards');
foreach($list as $user){
// 獲取用戶(hu)關聯的card模型數據
dump($user->cards);
}
如果你的數據集查詢返回的是數組,系統提供了一個load_relation助手函數可以完(wan)成同樣的功能。
// 查詢(xun)數據(ju)集(ji)
$list = User::all([1,2,3]);
// 延遲預載入
$list = load_relation($list,'cards');
foreach($list as $user){
// 獲取(qu)用(yong)戶關聯(lian)的(de)card模(mo)型數據
dump($user->cards);
}
