
本文介绍如何在 yii2 中遍历获奖者模型,关联查询对应用户和商品信息,并结构化组装为统一数组,最终输出为 api 可用的 json 数据。核心在于避免错误的多次覆盖式合并,改用追加方式构建结果集。
在构建 JSON API 时,常见需求是将多个关联模型(如 Winners、User、Products)的数据聚合为一个扁平、语义清晰的响应结构。你最初的尝试使用 ArrayHelper::merge() 在循环内反复赋值 $result,这会导致每次迭代都覆盖前一次结果,最终仅保留最后一个条目的数据——这不是“合并数组”,而是“丢弃历史”。
✅ 正确做法是:初始化空数组 $data = [],然后在循环中使用 PHP 的数组追加语法 $data[] = [...] 动态添加每个完整条目。这种方式逻辑清晰、性能可控,且天然适配 JSON 序列化。
以下为推荐实现(含关键注释):
use yii\helpers\ArrayHelper;
// 1. 获取前8位获奖者(ActiveRecord 对象数组)
$winners = Winners::find()->limit(8)->all();
// 2. 初始化结果容器(注意:此处声明为空数组,非 $data['winners'])
$data = [];
// 3. 遍历每位获奖者,关联查询并组装结构化数据
foreach ($winners as $winner) {
// 查询用户(推荐使用 findIdentity,确保用户存在且已激活)
$user = User::findIdentity($winner->user_id);
if (!$user) {
continue; // 跳过无效用户,避免后续报错
}
// 查询本地化商品(假设 localized() 是自定义 scope)
$product = Products::find()
->localized($lang)
->where(['coupon' => $winner->coupon])
->one();
if (!$product) {
continue; // 跳过无匹配商品的记录
}
// 4. 组装单条响应数据(字段名语义化,便于前端消费)
$data[] = [
'id' => $winner->id,
'user_name' => trim($user->firstname . ' ' . $user->lastname),
'user_avatar'=> $user->avatar_url ?? '',
'prize_image'=> $product->prize_image,
'win_title' => $product->win_title,
'coupon' => $winner->coupon,
'created_at' => $winner->created_at,
];
}
// 5. 返回 JSON 响应(Yii2 控制器中通常这样写)
return $this->asJson($data);⚠️ 注意事项:
- 避免在循环中调用 ArrayHelper::merge($a, $b) 试图“累积”数据——它仅合并两个数组,不支持追加到列表;
- 始终对关联查询结果做空值检查(if (!$user)),防止 Trying to get property of non-object 错误;
- 如需提升性能(尤其数据量增大时),建议改用 JOIN 查询 + with() 预加载,或使用 createCommand() 执行原生 SQL 一次性获取全部关联字段;
- 字段命名推荐使用下划线风格(如 user_name)以符合 JSON API 惯例,避免驼峰导致前端解析歧义。
该方案简洁、健壮、可读性强,是 Yii2 API 开发中处理多模型聚合的典型实践。










