每一個新手程序猿都會遇到一些奇奇怪怪的難題,好比說在兩個或者多個數據關係表的狀況下,須要以一個主表查詢出對應關係表的數據,以下關係表說明php
<?php // 獲取會員卡列表 $vips = Vip::find()->offset(0)->limit(10)->asArray()->all(); // 循環組裝會員用戶信息及會員卡附表數據 foreach($vips as &$row){ // 獲取會員卡用戶信息 $row['user'] = User::find()->andWhre(['user_id'=>$row['user_id']])->limit(1)->asArray()->one(); // 獲取會員卡附表信息 $row['fields'] = VipFIelds::find()->andWhere(['vip_id'=>'vip_id'])->limit(1)->asArray()->one(); } return $vips; ?>
[ { "vip_id": 1, "user_id": 1, "user": { "user_id": 1, "nickname": "小白", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 1, "realname": "小小白", "sex": 1, "email": "xiaobai@qq.com" } }, { "vip_id": 2, "user_id": 2, "user": { "user_id": 2, "nickname": "小米", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 2, "realname": "小小米", "sex": 1, "email": "xiaomi@qq.com" } } ]
<?php // 會員卡列表 $vips = Vip::find()->offset(0)->limit(10)->asArray()->all(); // 用戶id $userIds = array_unique(array_column($vips,'user_id')); // 會員卡id $vipIds = array_unique(array_column($vips,'vip_id')); // 會員卡用戶信息數據列表 $users = User::find()->andWhere(['user_id'=>$userIds])->asArray()->limit(count($userIds))->all(); // 重組會員卡信息數據 以user_id爲key $usersRow = array_column($users,null,'user_id'); // 會員卡附表數據列表 $fields = VipFields::find()->andWhere(['vip_id'=>$vipIds])->asArray()->limit(count($vipIds))->all(); // 重組會員卡附表數據 以 vip_id爲key $fieldsRow = array_column($fields,null,'vip_id'); foreach($vips as &$row){ // 組裝會員卡用戶信息 不存在 爲 null $row['user'] = $usersRow[$row['user_id']] ?? null; // 組裝會員卡附表信息 不存在 爲 null $row['fields'] = $fieldsRow[$row['vip']] ?? null; } return $vips; ?>
[ { "vip_id": 1, "user_id": 1, "user": { "user_id": 1, "nickname": "小白", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 1, "realname": "小小白", "sex": 1, "email": "xiaobai@qq.com" } }, { "vip_id": 2, "user_id": 2, "user": { "user_id": 2, "nickname": "小米", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 2, "realname": "小小米", "sex": 1, "email": "xiaomi@qq.com" } } ]
官方說明數據庫
注意,由於將執行 JOIN 查詢,因此你須要消除列名的歧義。api
定義數組
// 指定鏈接會員卡附表 public function getFields() { return $this->hasOne(VipFields::class,['vip_id'=>'vip_id']); } // 指定鏈接會員卡用戶表 public function getUser() { return $this->hasOne(User::class,['user_id'=>'user_id']); }
注意如下幾點:yii
1.當表名存在下劃線時,joinWith裏的表名首字母要小寫,下劃線結束後的第一個字母要大寫 2.有where條件時,字段名前的表名,有些跨數據庫的,數據庫名要寫全。
使用優化
<?php // 建立用戶模型 $query = Vip::find(); // 使用模型joinWith鏈接 $query->joinWith([ 'fields', 'user' ]); $list = $query->offset(0)->limit(10)->asArray()->all(); return $list; ?>
使用joinWith進行Vip模型鏈接時,同時使用field以及User模型鏈接的狀況下,那麼說明以vip作爲主表,以vip_fields及user表作爲附表,同時三表中必須存在關聯數據纔有查詢結果this
- 運行結果
[ { "vip_id": 1, "user_id": 1, "user": { "user_id": 1, "nickname": "小白", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 1, "realname": "小小白", "sex": 1, "email": "xiaobai@qq.com" } }, { "vip_id": 2, "user_id": 2, "user": { "user_id": 2, "nickname": "小米", "avatar": "http://xiaobai.png" }, "fields": { "vip_id": 2, "realname": "小小米", "sex": 1, "email": "xiaomi@qq.com" } } ]
不一樣的需求都有不一樣的代碼處理邏輯,以例1與例2爲示例,雖然例1也能實現接口需求,可是對於數據庫影響比較大,不推薦使用,例1雖然說處理步驟較多,可是對數據影響較小,能夠選擇例2使用,如發現更好的方案會繼續優化spa