You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何向JSON类型字段追加数据而非覆盖原有内容

实现方案

方案1:通用兼容方案(适配所有支持JSON字段的数据库)

核心逻辑是先将API响应按id分组,减少数据库交互次数,再查询已有值合并后统一更新:

// 按响应id分组,同id的所有响应归入同一组
$groupedResponses = collect($responses)->groupBy('id');

foreach ($groupedResponses as $resId => $items) {
    // 查询当前id已存储的JSON值,不存在则初始化空数组
    $existingValues = DB::table('table')->where('res_id', $resId)->value('myvalues');
    $existingValues = $existingValues ? json_decode($existingValues, true) : [];

    // 遍历同id的所有响应,追加新值
    foreach ($items as $item) {
        $newValue = json_decode($item->value, true);
        // 若新值本身是数组则合并,单条对象则直接追加
        if (is_array($newValue) && array_is_list($newValue)) {
            $existingValues = array_merge($existingValues, $newValue);
        } else {
            $existingValues[] = $newValue;
        }
    }

    // 合并完成后更新到数据库
    DB::table('table')->where('res_id', $resId)->update([
        'myvalues' => json_encode($existingValues)
    ]);
}

方案2:高性能原子操作方案(适配MySQL 5.7+/PostgreSQL等支持JSON原生操作的数据库)

使用数据库自带的JSON操作函数实现原子追加,无需提前查询,可避免并发场景下的竞态覆盖问题:

追加单个对象场景

foreach ($responses as $response) {
    $newValue = json_decode($response->value, true);
    DB::table('table')
        ->where('res_id', $response->id)
        ->update([
            'myvalues' => DB::raw('JSON_ARRAY_APPEND(IFNULL(myvalues, JSON_ARRAY()), "$", ?)'),
        ], [$newValue]);
}

合并多个值(新值本身为数组)场景

foreach ($responses as $response) {
    $newValue = $response->value; // 此处直接使用JSON格式的字符串即可
    DB::table('table')
        ->where('res_id', $response->id)
        ->update([
            'myvalues' => DB::raw('JSON_MERGE_PRESERVE(IFNULL(myvalues, JSON_ARRAY()), ?)'),
        ], [$newValue]);
}
注意事项
  • 建议将表中myvalues字段的默认值设为空JSON数组[],可省去空值判断逻辑
  • 同id响应量大时优先选择先分组再批量处理的逻辑,可大幅降低数据库IO压力
  • 存在并发更新同id记录的场景下必须使用原生JSON函数方案,避免先查后写导致的数据覆盖

内容的提问来源于stack exchange,提问作者ira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 22:54:05