Yii2 中高效合并获奖者、用户与商品数据并生成 JSON 响应

Yii2 中高效合并获奖者、用户与商品数据并生成 JSON 响应

本文介绍如何在 yii2 中遍历获奖者模型,关联查询对应用户和商品信息,并结构化组装为统一数组,最终输出为 api 可用的 json 数据。核心在于避免错误的多次覆盖式合并,改用追加方式构建结果集。

在构建 JSON API 时,常见需求是将多个关联模型(如 Winners、User、Products)的数据聚合为一个扁平、语义清晰的响应结构。你最初的尝试使用 ArrayHelper::merge() 在循环内反复赋值 $result,这会导致每次迭代都覆盖前一次结果,最终仅保留最后一个条目的数据——这不是“合并数组”,而是“丢弃历史”。

✅ 正确做法是:初始化空数组 $data = [],然后在循环中使用 PHP 的数组追加语法 $data[] = […] 动态添加每个完整条目。这种方式逻辑清晰、性能可控,且天然适配 JSON 序列化。

以下为推荐实现(含关键注释):

数说Social Research

数说Social Research

社媒领域的AI Agent,全能营销智能助手

下载

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 开发中处理多模型聚合的典型实践。

https://www.php.cn/faq/2035045.html

发表回复

Your email address will not be published. Required fields are marked *