每一个新手程序猿都会遇到一些奇奇怪怪的难题,好比说在两个或者多个数据关系表的状况下,须要以一个主表查询出对应关系表的数据,以下关系表说明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