Yii2 ActiveRecord多表關(guān)聯(lián)及多表關(guān)聯(lián)搜索的實(shí)現(xiàn)
Yii的ActiveRecord是與數(shù)據(jù)庫(kù)打交道的類,也即MVC中的M(模型層),也是ORM的O(Object)。
一個(gè)老生常談的問題。最近通過(guò)群里的反饋,覺得很多人還是沒有去理解這個(gè)問題。今天把這個(gè)問題講明白了,看看yii2 ActiveRecord是怎么個(gè)多表關(guān)聯(lián)以及如何去優(yōu)化這個(gè)關(guān)聯(lián)。
場(chǎng)景需求:
假設(shè)我們有一張用戶表user和一張用戶渠道表auth,兩張數(shù)據(jù)表通過(guò)user.id和auth.uid進(jìn)行一對(duì)一關(guān)聯(lián)?,F(xiàn)需要在user列表展示auth表的來(lái)源渠道source,且該渠道可搜索。
首先我們先通過(guò)gii生成user和auth系列相關(guān)的model和操作。此處不做詳細(xì)說(shuō)明,有關(guān)gii的操作可參考xxx
我看繼續(xù)看重要的幾個(gè)操作步驟:
1、找到user表對(duì)應(yīng)的AR模型類 common\models\User.php,在該類文件中進(jìn)行關(guān)聯(lián)auth表
/** * 關(guān)聯(lián)auth表 */ public function getAuth() { // hasOne要求返回兩個(gè)參數(shù) 第一個(gè)參數(shù)是關(guān)聯(lián)表的類名 第二個(gè)參數(shù)是兩張表的關(guān)聯(lián)關(guān)系 // 這里uid是auth表關(guān)聯(lián)id, 關(guān)聯(lián)user表的uid id是當(dāng)前模型的主鍵id return $this->hasOne(common\models\Auth::className(), ['uid' => 'id']); }
設(shè)置好了之后,并不代表兩張數(shù)據(jù)表自動(dòng)進(jìn)行關(guān)聯(lián)了!我們?cè)L問user列表頁(yè)(該列表頁(yè)采用gii生成,目前我們沒操作過(guò)),通過(guò)debug查看Database Queries不難發(fā)現(xiàn),實(shí)際中的query并沒有進(jìn)行關(guān)聯(lián)auth表
2、在gridview中添加關(guān)聯(lián)表的來(lái)源渠道字段source
<?= GridView::widget([ // other codes 'columns' => [ // other columns 'auth.source', ] ]); ?>
有同學(xué)感覺疑問了,上面不是說(shuō)了沒進(jìn)行關(guān)聯(lián)嗎,這個(gè)怎么可以直接使用auth.source?
先別急,此時(shí)我們打開debug看看實(shí)際的query。
我們會(huì)發(fā)現(xiàn)有很多類似 select * from `auth` where uid = xxx;之類的操作,如果你的分頁(yè)默認(rèn)20條數(shù)據(jù)時(shí),會(huì)有20個(gè)類似的query。
我們先搞明白發(fā)生了什么?
實(shí)際上這屬于php的基礎(chǔ)知識(shí)了。讀取和寫入對(duì)象的一個(gè)不存在的成員變量時(shí), __get() __set() 魔術(shù)函數(shù)會(huì)被自動(dòng)調(diào)用。yii也是利用了這一點(diǎn)對(duì)其進(jìn)行了實(shí)現(xiàn)!
該操作跟大部分人在gridview中封裝方法獲取關(guān)聯(lián)表數(shù)據(jù)幾乎一致,但是!20條sql的查詢明顯增加了眾多的開銷。如果這里是left join操作多好!
3、優(yōu)化sql
我們需要優(yōu)化的是:
20條sql變1條sql
只獲取關(guān)聯(lián)表需要的字段
有同學(xué)要嚷嚷了,這里是yii自帶的操作,怎么優(yōu)化?我們回到數(shù)據(jù)源的獲取上,發(fā)現(xiàn)user列表的數(shù)據(jù)是通過(guò)userSearch model的search方法提供的。
也就是說(shuō)我們的數(shù)據(jù)查詢實(shí)際上就沒有去進(jìn)行關(guān)聯(lián)表查詢!既然如此,我們就在UserSearch加上關(guān)聯(lián)查詢
$query = User::find(); $query->joinWith(['auth']); $query->select("user.*, auth.source");
我們?cè)賮?lái)刷新下user列表頁(yè),然后通過(guò)debug分析發(fā)現(xiàn)有兩條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個(gè)uid);
也就是說(shuō)我么已經(jīng)達(dá)到了優(yōu)化sql的目的,通過(guò)debug分析發(fā)現(xiàn),DB的查詢時(shí)間少了很多。
4、關(guān)聯(lián)表字段增加查詢
gridview中的搜索模型也是通過(guò)searchModel實(shí)現(xiàn)的,該模型通過(guò)rules控制著哪個(gè)字段可搜索,哪個(gè)字段不可搜索。
我們現(xiàn)在需要增加關(guān)聯(lián)表的source可搜索,因此我們?cè)趕earchModel中定義一個(gè)屬性source且添加到rules中
public $source; public function rules() { return [ // other rules ['source', 'safe'], ]; }
接著我們把gridview中的auth.source修改一下
// 'auth.source', [ 'attribute' => 'source', 'value' => 'auth.source', 'label' => '渠道來(lái)源', ],
到這里我們界面上是ok的,要實(shí)現(xiàn)程序上的搜索還差一步,我們?cè)跀?shù)據(jù)源獲取的地方加上新增的source條件即可
$query->andFilterWhere([ // other params 'auth.source' => $this->source, ]);
下面給大家補(bǔ)充yii中ActiveRecord的一些用法
1,對(duì)象轉(zhuǎn)數(shù)組
$model = new ActiveRecord();
$model.toArray();
由于ActiveRecord不是簡(jiǎn)單數(shù)組,不能直接json_encode,否則信息不完整。
解決辦法:$model.toArray();這樣就變?yōu)楹?jiǎn)單數(shù)組了,可以進(jìn)行json_encode了。
2,通過(guò)名字或其他字段直接獲取ActiveRecord的id。
$nIdcId = idc_info::model()->find('name like :name',array(':name'=>"%".$strIdcName."%"))->id;
我以前經(jīng)常使用的辦法是(現(xiàn)在發(fā)現(xiàn)很土):
$idc = Idc::model()->find("..."); $id = $idc->id;
3,對(duì)model的理解
$accModel = call_user_func(array(ActiveRecordName, 'model')); $model = $accModel->findByPk($id);
以上所述是小編給大家介紹的Yii2 ActiveRecord多表關(guān)聯(lián)及多表關(guān)聯(lián)搜索的實(shí)現(xiàn)的相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Yii2.0小部件GridView(兩表聯(lián)查/搜索/分頁(yè))功能的實(shí)現(xiàn)代碼
- yii2實(shí)現(xiàn)分頁(yè),帶搜索的分頁(yè)功能示例
- Yii2實(shí)現(xiàn)同時(shí)搜索多個(gè)字段的方法
- Yii2實(shí)現(xiàn)讓關(guān)聯(lián)字段支持搜索功能的方法
- 淺析Yii2 GridView實(shí)現(xiàn)下拉搜索教程
- yii2實(shí)現(xiàn)根據(jù)時(shí)間搜索的方法
- yii2帶搜索功能的下拉框?qū)嵗斀?/a>
- Yii2-GridView 中讓關(guān)聯(lián)字段帶搜索和排序功能示例
- Yii2框架整合Xunsearch搜索引擎的方法
- yii2組件之下拉框帶搜索功能的示例代碼(yii-select2)
- Yii2.0框架實(shí)現(xiàn)帶分頁(yè)的多條件搜索功能示例
相關(guān)文章
php+memcache實(shí)現(xiàn)的網(wǎng)站在線人數(shù)統(tǒng)計(jì)代碼
這篇文章主要介紹了php+memcache實(shí)現(xiàn)的網(wǎng)站在線人數(shù)統(tǒng)計(jì)代碼,代碼例子簡(jiǎn)潔實(shí)用,需要的朋友可以參考下2014-07-07Yii2實(shí)現(xiàn)跨mysql數(shù)據(jù)庫(kù)關(guān)聯(lián)查詢排序功能代碼
本篇文章主要介紹了Yii2實(shí)現(xiàn)跨mysql數(shù)據(jù)庫(kù)關(guān)聯(lián)查詢排序功能示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02php實(shí)現(xiàn)window平臺(tái)的checkdnsrr函數(shù)
這篇文章主要介紹了php實(shí)現(xiàn)window平臺(tái)的checkdnsrr函數(shù),PHP的自帶checkdnsrr函數(shù)只在linux平臺(tái)有效,本文就模擬出了一個(gè)window下可以使用的checkdnsrr函數(shù),需要的朋友可以參考下2015-05-05smarty內(nèi)置函數(shù)foreach用法實(shí)例
這篇文章主要介紹了smarty內(nèi)置函數(shù)foreach用法,實(shí)例分析了smarty內(nèi)置的foreach函數(shù)使用技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2015-01-01