《PHP實戰(zhàn):Yii2 ActiveRecord多表關(guān)聯(lián)及多表關(guān)聯(lián)搜索的實現(xiàn)》要點:
本文介紹了PHP實戰(zhàn):Yii2 ActiveRecord多表關(guān)聯(lián)及多表關(guān)聯(lián)搜索的實現(xiàn),希望對您有用。如果有疑問,可以聯(lián)系我們。
相關(guān)主題:YII框架
PHP實戰(zhàn)Yii的ActiveRecord是與數(shù)據(jù)庫打交道的類,也即MVC中的M(模型層),也是ORM的O(Object).
PHP實戰(zhàn)一個老生常談的問題.最近通過群里的反饋,覺得很多人還是沒有去理解這個問題.今天把這個問題講明白了,看看yii2 ActiveRecord是怎么個多表關(guān)聯(lián)以及如何去優(yōu)化這個關(guān)聯(lián).
PHP實戰(zhàn)場景需求:
PHP實戰(zhàn)假設(shè)我們有一張用戶表user和一張用戶渠道表auth,兩張數(shù)據(jù)表通過user.id和auth.uid進行一對一關(guān)聯(lián).現(xiàn)需要在user列表展示auth表的來源渠道source,且該渠道可搜索.
PHP實戰(zhàn)首先我們先通過gii生成user和auth系列相關(guān)的model和操作.此處不做詳細(xì)說明,有關(guān)gii的操作可參考xxx
PHP實戰(zhàn)我看繼續(xù)看重要的幾個操作步驟:
PHP實戰(zhàn)1、找到user表對應(yīng)的AR模型類 common\models\User.php,在該類文件中進行關(guān)聯(lián)auth表
PHP實戰(zhàn)
/**
* 關(guān)聯(lián)auth表
*/
public function getAuth()
{
// hasOne要求返回兩個參數(shù) 第一個參數(shù)是關(guān)聯(lián)表的類名 第二個參數(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']);
}
PHP實戰(zhàn)設(shè)置好了之后,并不代表兩張數(shù)據(jù)表自動進行關(guān)聯(lián)了!我們訪問user列表頁(該列表頁采用gii生成,目前我們沒操作過),通過debug查看Database Queries不難發(fā)現(xiàn),實際中的query并沒有進行關(guān)聯(lián)auth表
PHP實戰(zhàn)2、在gridview中添加關(guān)聯(lián)表的來源渠道字段source
PHP實戰(zhàn)
<?= GridView::widget([
// other codes
'columns' => [
// other columns
'auth.source',
]
]); ?>
PHP實戰(zhàn)有同學(xué)感覺疑問了,上面不是說了沒進行關(guān)聯(lián)嗎,這個怎么可以直接使用auth.source?
PHP實戰(zhàn)先別急,此時我們打開debug看看實際的query.
PHP實戰(zhàn)我們會發(fā)現(xiàn)有很多類似 select * from `auth` where uid = xxx;之類的操作,如果你的分頁默認(rèn)20條數(shù)據(jù)時,會有20個類似的query.
PHP實戰(zhàn)我們先搞明白發(fā)生了什么?
PHP實戰(zhàn)實際上這屬于php的基礎(chǔ)知識了.讀取和寫入對象的一個不存在的成員變量時, __get() __set() 魔術(shù)函數(shù)會被自動調(diào)用.yii也是利用了這一點對其進行了實現(xiàn)!
PHP實戰(zhàn)該操作跟大部分人在gridview中封裝方法獲取關(guān)聯(lián)表數(shù)據(jù)幾乎一致,但是!20條sql的查詢明顯增加了眾多的開銷.如果這里是left join操作多好!
PHP實戰(zhàn)3、優(yōu)化sql
PHP實戰(zhàn)我們需要優(yōu)化的是:
PHP實戰(zhàn)20條sql變1條sql
PHP實戰(zhàn)只獲取關(guān)聯(lián)表需要的字段
PHP實戰(zhàn)有同學(xué)要嚷嚷了,這里是yii自帶的操作,怎么優(yōu)化?我們回到數(shù)據(jù)源的獲取上,發(fā)現(xiàn)user列表的數(shù)據(jù)是通過userSearch model的search方法提供的.
PHP實戰(zhàn)也就是說我們的數(shù)據(jù)查詢實際上就沒有去進行關(guān)聯(lián)表查詢!既然如此,我們就在UserSearch加上關(guān)聯(lián)查詢
PHP實戰(zhàn)
$query = User::find();
$query->joinWith(['auth']);
$query->select("user.*, auth.source");
PHP實戰(zhàn)我們再來刷新下user列表頁,然后通過debug分析發(fā)現(xiàn)有兩條sql引起了我們的注意
PHP實戰(zhàn)
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);
PHP實戰(zhàn)也就是說我么已經(jīng)達到了優(yōu)化sql的目的,通過debug分析發(fā)現(xiàn),DB的查詢時間少了很多.
PHP實戰(zhàn)4、關(guān)聯(lián)表字段增加查詢
PHP實戰(zhàn)gridview中的搜索模型也是通過searchModel實現(xiàn)的,該模型通過rules控制著哪個字段可搜索,哪個字段不可搜索.
PHP實戰(zhàn)我們現(xiàn)在需要增加關(guān)聯(lián)表的source可搜索,因此我們在searchModel中定義一個屬性source且添加到rules中
PHP實戰(zhàn)
public $source;
public function rules()
{
return [
// other rules
['source', 'safe'],
];
}
PHP實戰(zhàn)接著我們把gridview中的auth.source修改一下
PHP實戰(zhàn)
// 'auth.source',
[
'attribute' => 'source',
'value' => 'auth.source',
'label' => '渠道來源',
],
PHP實戰(zhàn)到這里我們界面上是ok的,要實現(xiàn)程序上的搜索還差一步,我們在數(shù)據(jù)源獲取的地方加上新增的source條件即可
PHP實戰(zhàn)
$query->andFilterWhere([
// other params
'auth.source' => $this->source,
]);
PHP實戰(zhàn)下面給大家補充yii中ActiveRecord的一些用法
PHP實戰(zhàn)1,對象轉(zhuǎn)數(shù)組
PHP實戰(zhàn)$model = new ActiveRecord();
$model.toArray();
PHP實戰(zhàn)由于ActiveRecord不是簡單數(shù)組,不能直接json_encode,否則信息不完整.
PHP實戰(zhàn)解決辦法:$model.toArray();這樣就變?yōu)楹唵螖?shù)組了,可以進行json_encode了.
PHP實戰(zhàn)2,通過名字或其他字段直接獲取ActiveRecord的id.
PHP實戰(zhàn)
$nIdcId = idc_info::model()->find('name like :name',array(':name'=>"%".$strIdcName."%"))->id;
PHP實戰(zhàn)我以前經(jīng)常使用的辦法是(現(xiàn)在發(fā)現(xiàn)很土):
PHP實戰(zhàn)
$idc = Idc::model()->find("...");
$id = $idc->id;
PHP實戰(zhàn)3,對model的理解
PHP實戰(zhàn)
$accModel = call_user_func(array(ActiveRecordName, 'model'));
$model = $accModel->findByPk($id);
PHP實戰(zhàn)以上所述是小編給大家介紹的Yii2 ActiveRecord多表關(guān)聯(lián)及多表關(guān)聯(lián)搜索的實現(xiàn)的相關(guān)知識,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的.在此也非常感謝大家對維易PHP網(wǎng)站的支持!
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/6071.html