如何在Yii2 API中获取包含关联用户数据的客户端列表?
Yii2 API返回包含关联用户数据的客户端列表实现方案
问题描述
需要在Yii2 API中返回如下格式的响应,每个客户端数据包含其关联的用户数据:
示例响应结构:
{ "clients": [ { "id": 1, "name": "client_1", "users": [ {"id": 1, "name": "user_1", "clients_id": 1}, {"id": 2, "name": "user_2", "clients_id": 1} ] }, { "id": 2, "name": "client_2", "users": [ {"id": 3, "name": "user_3", "clients_id": 2}, {"id": 4, "name": "user_4", "clients_id": 2} ] } ] }
请问如何编写对应的Yii2代码?是否可以使用Query Builder,还是需要使用MySQL语法?
实现方案
方法一:使用ActiveRecord关联(推荐)
这是Yii2中最简洁高效的方式,前提是已定义Client和User模型,并配置好关联关系。
- 定义模型关联
在Client模型中添加关联方法,指定与User表的关联规则:
// models/Client.php public function getUsers() { // 假设User表外键为clients_id,关联到Client表的id字段 return $this->hasMany(User::class, ['clients_id' => 'id']); }
- 控制器中查询并返回数据
在API控制器的动作方法中,通过with()预加载关联数据,避免N+1查询问题:
// controllers/Api/ClientController.php public function actionIndex() { // 查询所有客户端,并预加载关联的用户数据 $clients = Client::find()->with('users')->all(); // 设置响应格式为JSON并返回 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return [ 'clients' => $clients ]; }
返回的JSON结构会自动包含每个客户端的users数组,完全匹配需求格式。
方法二:使用Query Builder实现
如果不想依赖ActiveRecord,也可以用Query Builder手动构建查询并组装数据:
基础版(存在N+1查询问题,小数据量可用)
// controllers/Api/ClientController.php public function actionIndex() { $db = Yii::$app->db; // 查询所有客户端基础数据 $clients = $db->createCommand('SELECT id, name FROM client')->queryAll(); // 遍历客户端,查询对应用户数据并组装 foreach ($clients as &$client) { $client['users'] = $db->createCommand( 'SELECT id, name, clients_id FROM user WHERE clients_id = :clientId', [':clientId' => $client['id']] )->queryAll(); } // 返回JSON响应 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return [ 'clients' => $clients ]; }
优化版(解决N+1查询问题)
// controllers/Api/ClientController.php public function actionIndex() { $db = Yii::$app->db; // 查询所有客户端 $clients = $db->createCommand('SELECT id, name FROM client')->queryAll(); $clientIds = array_column($clients, 'id'); // 一次性查询所有关联用户,按clients_id分组 $users = $db->createCommand( 'SELECT id, name, clients_id FROM user WHERE clients_id IN (:clientIds)', [':clientIds' => $clientIds] )->queryAll(); // 将用户数据按客户端ID分组映射 $userMap = []; foreach ($users as $user) { $userMap[$user['clients_id']][] = $user; } // 组装客户端数据 foreach ($clients as &$client) { $client['users'] = $userMap[$client['id']] ?? []; } // 返回JSON响应 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return [ 'clients' => $clients ]; }
关于是否需要MySQL语法
不需要直接编写复杂的原生MySQL嵌套查询,Yii2的ActiveRecord关联或优化后的Query Builder完全可以满足需求。直接写原生SQL虽然可行,但会失去框架提供的ORM优势(如自动表前缀、查询安全、可维护性等),除非有特殊复杂场景,否则不推荐。
内容的提问来源于stack exchange,提问作者Darshan Soni
相关产品推荐
相关产品推荐

