首頁  >  文章  >  php教程  >  Yii2 ActiveRecord多重表格關聯及多重表格關聯搜尋的實現

Yii2 ActiveRecord多重表格關聯及多重表格關聯搜尋的實現

高洛峰
高洛峰原創
2016-12-23 16:52:301332瀏覽

Yii的ActiveRecord是與資料庫打交道的類,也是MVC中的M(模型層),也是ORM的O(Object)。

一個老生常談的問題。最近透過群組的回饋,覺得很多人還是沒有去理解這個問題。今天把這個問題講明白了,看看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(common\models\Auth::className(), ['uid' => 'id']);
}

   

設定好了之後,並不代表兩張資料表自動進行關聯了!我們訪問user列表頁(該列表頁採用gii生成,目前我們沒操作過),透過debug查看Database Queries不難發現,實際中的query並沒有進行關聯auth表

2、在gridview中添加關聯表的來源管道欄位source

<?= GridView::widget([
// other codes
&#39;columns&#39; => [
// other columns
&#39;auth.source&#39;,
]
]); ?>

   

有同學感覺疑問了,上面不是說了沒進行關聯嗎,這個怎麼可以直接使用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自帶的欄位

有同學要嚷嚷了,這裡是yii自帶的欄位

有同學要嚷嚷了,這裡是yii自帶的操作,最佳化?我們回到資料來源的取得上,發現user清單的資料是透過userSearch model的search方法提供的。

也就是說我們的資料查詢其實就沒有去進行關聯表查詢!既然如此,我們就在UserSearch加上關聯查詢

$query = User::find();
$query->joinWith([&#39;auth&#39;]);
$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
[&#39;source&#39;, &#39;safe&#39;],
];
}

   

接著

到這裡我們介面上是ok的,要實現程式上的搜尋還差一步,我們在資料來源取得的地方加上新增的source條件即可

// &#39;auth.source&#39;,
[
&#39;attribute&#39; => &#39;source&#39;,
&#39;value&#39; => &#39;auth.source&#39;,
&#39;label&#39; => &#39;渠道来源&#39;,
],

   

下面給大家補充yii中ActiveRecord的一些用法

1,物件轉數組

$model = new ActiveRecord(); 

$model.toArray();

由於ActiveRecord不是簡單數組,不能直接json_encode,否則資訊不完整。


解決方法:$model.toArray();這樣就變成簡單陣列了,可以進行json_encode了。

2,透過名字或其他欄位直接取得ActiveRecord的id。

$query->andFilterWhere([
// other params
&#39;auth.source&#39; => $this->source,
]);

   

我以前常用的方法是(現在發現很土):

$nIdcId = idc_info::model()->find(&#39;name like :name&#39;,array(&#39;:name&#39;=>"%".$strIdcName."%"))->id;

   

3,對上model 的理解是以上給大家介紹的Yii2 ActiveRecord多表關聯及多表關聯搜尋的實現的相關知識,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對PHP中文網的支持!

更多Yii2 ActiveRecord多表關聯及多表關聯搜尋的實現相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn