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

Laravel更新订单商品后API返回旧数据 响应滞后一次请求问题

问题现象

发起订单商品更新请求时,数据库数据已更新完成,但API响应存在固定一次的数据滞后:原订单总价100,提交更新后预期为150,本次接口返回、以及更新后立即查询拿到的仍是旧值100;再次提交更新将总价调整为200时,返回值才是上一次更新后的150,数据始终比数据库实际值慢一步,必须发起下一次请求才能拿到本次更新的正确结果。

问题涉及的更新代码如下:

public function updateProducts(AdminUpdateOrderRequest $request, $id)
{
    $orderValidated = $request->validated();
    $order = Order::findOrFail($id);

    if (isset($orderValidated['products'])) {
        $order->products()->sync($orderValidated['products']);
    }

    DB::table('order_product')->where('order_id', $order->id)
        ->update([
            'total_buy_price' => DB::raw('order_product.quantity * (select converted_buy_price from products where id = order_product.product_id)'),
            'total_selling_price' => DB::raw('order_product.quantity * (select converted_selling_price from products where id = order_product.product_id) ')
        ]);

    DB::table('orders')->where('id', $order->id)->update([
        'cost_price' => DB::raw('(select SUM(order_product.total_buy_price) from order_product where order_product.order_id = ' . $order->id . ')'),
        'total_price' => DB::raw('(select SUM(order_product.total_selling_price) from order_product where order_product.order_id = ' . $order->id . ')'),
        'remaining' => DB::raw('(select SUM(order_product.total_buy_price) from order_product where order_product.order_id = ' . $order->id . ' - ' . $order->payments->sum('amount') . ')'),
        'products_count' => DB::raw('(select SUM(quantity) from order_product where order_product.order_id = ' . $order->id . ')')
    ]);

    DB::table('packages')->update([
        'selling' => DB::raw('(select SUM(orders.total_price) from orders where orders.package_id = packages.id)'),
        'amount' => DB::raw('(select SUM(orders.total_price) from orders where orders.package_id = packages.id)'),
        'cost' => DB::raw('(select SUM(orders.cost_price) from orders where orders.package_id = packages.id)'),
    ]);

    return OrderResource::make($order)->additional([
        'success' => true,
    ]);
}
故障原因

核心问题是Eloquent模型的内存数据和数据库实际数据不同步:

  • 代码开头通过Order::findOrFail($id)取出的$order是存在于当前请求内存中的模型实例,存储的是查询当下的旧属性值
  • 后续所有价格、统计字段的更新,都是通过DB::table()直接执行SQL操作数据库,全程没有修改内存中$order实例的属性
  • 最终返回响应时,OrderResource读取的是内存里的旧$order数据,自然返回更新前的值。下一次请求进入时会重新从数据库查询,就会拿到上一次更新的结果,表现为固定滞后一次。

额外隐藏bug:remaining字段的SQL括号位置错误,当前写法会先计算order_id = 订单ID - 已支付金额的查询条件,会导致统计结果完全错误。

修复方法

所有更新操作执行完成后,刷新模型的内存数据,再传给资源返回即可,同时修正remaining字段的SQL逻辑。
两种可选实现方式:

  1. 调用模型自带的refresh()方法刷新属性,同时预加载资源需要的关联关系避免N+1查询:
// 原有更新逻辑中修正remaining字段的SQL括号问题
$paidTotal = $order->payments->sum('amount');
DB::table('orders')->where('id', $order->id)->update([
    'cost_price' => DB::raw('(select SUM(order_product.total_buy_price) from order_product where order_product.order_id = ' . $order->id . ')'),
    'total_price' => DB::raw('(select SUM(order_product.total_selling_price) from order_product where order_product.order_id = ' . $order->id . ')'),
    // 先计算商品总价,再减去已支付金额
    'remaining' => DB::raw('(select SUM(order_product.total_buy_price) from order_product where order_product.order_id = ' . $order->id . ') - ' . $paidTotal),
    'products_count' => DB::raw('(select SUM(quantity) from order_product where order_product.order_id = ' . $order->id . ')')
]);
// packages表更新逻辑保持不变

// 刷新模型数据,加载关联
$order->refresh();
$order->load(['products', 'payments']);

return OrderResource::make($order)->additional([
    'success' => true,
]);
  1. 所有更新完成后,重新从数据库查询最新的订单实例,效果完全一致:
// 所有更新逻辑执行完成后
$freshOrder = Order::with(['products', 'payments'])->findOrFail($id);
return OrderResource::make($freshOrder)->additional([
    'success' => true,
]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:24:24