摘要:今天把這個問題講明白了,看看是怎么個多表關聯以及如何去優化這個關聯。現需要在列表展示表的來源渠道,且該渠道可搜索。關聯表字段增加查詢中的搜索模型也是通過實現的,該模型通過控制著哪個字段可搜索,哪個字段不可搜索。
作者:白狼 出處:http://www.manks.top/yii2_many_ar_relation_search.html 本文版權歸作者,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
一個老生常談的問題。最近通過群里的反饋,覺得很多人還是沒有去理解這個問題。今天把這個問題講明白了,看看yii2 ActiveRecord是怎么個多表關聯以及如何去優化這個關聯。
場景需求:
假設我們有一張用戶表user和一張用戶渠道表auth,兩張數據表通過user.id和auth.uid進行一對一關聯。現需要在user列表展示auth表的來源渠道source,且該渠道可搜索。
首先我們先通過gii生成user和auth系列相關的model和操作。此處不做詳細說明,有關gii的操作可參考xxx
我看繼續看重要的幾個操作步驟:
1、找到user表對應的AR模型類 commonmodelsUser.php,在該類文件中進行關聯auth表
/** * 關聯auth表 */ public function getAuth() { // hasOne要求返回兩個參數 第一個參數是關聯表的類名 第二個參數是兩張表的關聯關系 // 這里uid是auth表關聯id, 關聯user表的uid id是當前模型的主鍵id return $this->hasOne(commonmodelsAuth::className(), ["uid" => "id"]); }
設置好了之后,并不代表兩張數據表自動進行關聯了!我們訪問user列表頁(該列表頁采用gii生成,目前我們沒操作過),通過debug查看Database Queries不難發現,實際中的query并沒有進行關聯auth表
2、在gridview中添加關聯表的來源渠道字段source
= GridView::widget([ // other codes "columns" => [ // other columns "auth.source", ] ]); ?>
有同學感覺疑問了,上面不是說了沒進行關聯嗎,這個怎么可以直接使用auth.source?
先別急,此時我們打開debug看看實際的query。
我們會發現有很多類似 select * from auth where uid = xxx;之類的操作,如果你的分頁默認20條數據時,會有20個類似的query。
我們先搞明白發生了什么?
實際上這屬于php的基礎知識了。讀取和寫入對象的一個不存在的成員變量時, __get() __set() 魔術函數會被自動調用。yii也是利用了這一點對其進行了實現!
該操作跟大部分人在gridview中封裝方法獲取關聯表數據幾乎一致,但是!20條sql的查詢明顯增加了眾多的開銷。如果這里是left join操作多好!
3、優化sql
我們需要優化的是:
20條sql變1條sql
只獲取關聯表需要的字段
有同學要嚷嚷了,這里是yii自帶的操作,怎么優化?我們回到數據源的獲取上,發現user列表的數據是通過userSearch model的search方法提供的。
也就是說我們的數據查詢實際上就沒有去進行關聯表查詢!既然如此,我們就在UserSearch加上關聯查詢
$query = User::find(); $query->joinWith(["auth"]); $query->select("user.*, auth.source");
我們再來刷新下user列表頁,然后通過debug分析發現有兩條sql引起了我們的注意
SELECT `user`.*, `auth`.`source` FROM `user` LEFT JOIN `auth` ON `user`.`id` = `auth`.`uid` LIMIT 20 SELECT * FROM `auth` WHERE `user_id` IN (20個uid);
也就是說我么已經達到了優化sql的目的,通過debug分析發現,DB的查詢時間少了很多。
4、關聯表字段增加查詢
gridview中的搜索模型也是通過searchModel實現的,該模型通過rules控制著哪個字段可搜索,哪個字段不可搜索。
我們現在需要增加關聯表的source可搜索,因此我們在searchModel中定義一個屬性source且添加到rules中
public $source; public function rules() { return [ // other rules ["source", "safe"], ]; }
接著我們把gridview中的auth.source修改一下
// "auth.source", [ "attribute" => "source", "value" => "auth.source", "label" => "渠道來源", ],
到這里我們界面上是ok的,要實現程序上的搜索還差一步,我們在數據源獲取的地方加上新增的source條件即可
$query->andFilterWhere([ // other params "auth.source" => $this->source, ]);
[考慮目前國內網站大部分采集文章十分頻繁,更有甚者不注明原文出處,原作者更希望看客們查看原文,以防有任何問題不能更新所有文章,避免誤導!]
查看原文
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21746.html
摘要:前言是特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。需求分析使用一條查詢語句就能把列表的數據全部展現出來,列表包含一對一,一對多,以及多對多的關系。不能破壞自有的表頭排序功能,以及中的存值。相關資料中多表關聯查詢 前言 hasOne、hasMany是Yii2特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。為什么?因為這種方式關聯查詢出來...
摘要:前言是特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。需求分析使用一條查詢語句就能把列表的數據全部展現出來,列表包含一對一,一對多,以及多對多的關系。不能破壞自有的表頭排序功能,以及中的存值。相關資料中多表關聯查詢 前言 hasOne、hasMany是Yii2特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。為什么?因為這種方式關聯查詢出來...
摘要:前言是特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。需求分析使用一條查詢語句就能把列表的數據全部展現出來,列表包含一對一,一對多,以及多對多的關系。不能破壞自有的表頭排序功能,以及中的存值。相關資料中多表關聯查詢 前言 hasOne、hasMany是Yii2特有的用于多表關聯查詢的函數,平時在使用多表關聯查詢的時候建議使用它們。為什么?因為這種方式關聯查詢出來...
摘要:第二個參數是一個數組,其中鍵為所關聯的模型中的屬性,值為當前模型中的屬性。這里注意中的第二個是指關聯的中的,第一個是指中的。 首先先來說明一下表結構 表結構 現在有訂單表、用戶表、商品清單表、商品庫存表 showImg(https://segmentfault.com/img/bVRcME?w=833&h=244); showImg(https://segmentfault.com/i...
閱讀 2089·2021-11-02 14:48
閱讀 2765·2019-08-30 14:19
閱讀 2935·2019-08-30 13:19
閱讀 1303·2019-08-29 16:17
閱讀 3239·2019-08-26 14:05
閱讀 2994·2019-08-26 13:58
閱讀 3082·2019-08-23 18:10
閱讀 1110·2019-08-23 18:04