YII2-关系数据表组装

55次阅读

共计 2137 个字符,预计需要花费 6 分钟才能阅读完成。

前言

每个新手程序猿都会遇到一些奇奇怪怪的难题, 比如说在两个或者多个数据关系表的情况下, 需要以一个主表查询出对应关系表的数据, 如下关系表说明

准备

数据表说明

  • 用户表(user)

  • 会员卡表(vip)

  • 会员卡附表(vip_fields)

使用场景

  • 在很多时候数据列表需要关联多表字段才能满足需求

需求

  • 会员卡列表
  • 需要有会员昵称 / 头像 / 姓名 / 性别邮箱地址 / 会员 id

实现

  • 根据 (会员卡) 找出会员用户信息已经会员卡附表数据进行关联, 以下是两种示例

例 1

  <?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"
        }
    }
]

例 2

 <?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"
        }
    }
]

后言

  • 例 1 在 foreach 里面进行数据查询, 数据库请求频繁, 导致数据库压力较大, 数据库请求次数 1+(N*2) 次, 对数据库影响较大
  • 例 2 在查询出会员卡主表后在将关联表关联 id 单独取出成为数组再进行一批列表查询, 重组, 数据库请求次数 3 次

总结

不同的需求都有不同的代码处理逻辑, 以例 1 与例 2 为示例, 虽然例 1 也能实现接口需求, 但是对于数据库影响比较大, 不推荐使用, 例 1 虽说处理步骤较多, 但是对数据影响较小, 可以选择例 2 使用, 如发现更好的方案会继续优化

正文完
 0