You need to enable JavaScript to run this app. 如何用单个方法实现多表关联数据插入及解决Axios 405错误
优惠活动
大模型
产品
解决方案
定价
更多

如何用单个方法实现多表关联数据插入及解决Axios 405错误

405错误核心根因
  • 405代表“请求方法不被允许”,触发原因主要有三类:
    • 后端/api/commander路径注册的路由不支持POST方法
    • 前端请求路径拼写错误,和后端注册的路由路径不匹配
    • Laravel CSRF校验拦截返回的异常状态码,被前端Axios误识别为405
全链路代码现存问题(不止405)
  • 前端提交逻辑完全缺失核心业务数据:当前store()方法仅附加了made_by一个字段,没有把购物车商品列表、优惠金额等后端必须的入参传给接口
  • 控制器逻辑存在多处语法和逻辑错误:
    • 集合转换的闭包没有返回值,导致处理后的变量为空
    • 对数组格式的请求数据直接调用->update()方法,数组本身不存在Eloquent模型的update()能力
    • 方法接收的$id参数,前端请求中没有对应传入,会直接导致路由参数绑定失败
    • 分别创建了两个独立的RestauCommande实例,一个做了赋值但从未入库,另一个用create()方法生成的实例和前者没有关联,最后调用关联方法时会因为没有主键ID导致写入失败
  • 缺少数据库事务保障:三张表的写入属于强关联操作,任意一步执行失败都会产生脏数据(比如库存扣减成功但订单未生成)
可直接落地的修正方案

路由层修正

在routes/api.php中明确注册POST方法的路由,去掉多余的必选参数:

use App\Http\Controllers\CommandeController;

Route::post('/commander', [CommandeController::class, 'store']);

前端逻辑修正

  • 在页面头部引入CSRF Token的meta标签,全局配置Axios默认请求头携带该Token,避免被中间件拦截
  • 重写提交逻辑,把购物车全量数据拼入请求参数:
store() {
  const formData = new FormData();
  // 携带操作人ID
  formData.append(
    "made_by",
    document.querySelector("meta[name='users_id']").getAttribute("content")
  );
  // 携带优惠金额
  formData.append("remise", this.form.remise ?? 0);
  // 把购物车列表序列化后作为商品入参传递
  formData.append(
    "produits",
    JSON.stringify(this.cart.map(item => ({
      produit_id: item.id,
      quantite: item.quantity,
      prix_unitaire: item.prix
    })))
  );

  axios.post("/api/commander", formData)
    .then(res => {
      // 提交成功后清空购物车、关闭弹窗
      this.cart = [];
      this.$refs.myModalRefProduit.hide();
    })
    .catch(err => {
      console.error("订单提交失败:", err);
    })
}

后端控制器修正

引入数据库事务保障三表写入的原子性,修正所有逻辑错误:

public function store(Request $request)
{
    return \DB::transaction(function () use ($request) {
        // 入参校验
        $validated = $request->validate([
            'produits' => 'required|array',
            'produits.*.produit_id' => 'exists:products,id',
            'produits.*.quantite' => 'numeric|min:1',
            'remise' => 'nullable|numeric|min:0'
        ]);

        // 循环扣减商品库存,同时组装关联表数据
        $orderItems = collect($validated['produits'])->map(function ($item) {
            $product = Produits::find($item['produit_id']);
            // 执行库存扣减
            $product->decrement('stock_actuel', $item['quantite']);
            // 组装商品行数据
            return new CommandesProduits([
                'produit_id' => $item['produit_id'],
                'prix_unitaire' => $item['prix_unitaire'],
                'quantite' => $item['quantite'],
                'total_ligne' => $item['prix_unitaire'] * $item['quantite']
            ]);
        });

        // 计算订单总金额
        $subTotal = $orderItems->sum('total_ligne');
        $grandTotal = $subTotal - $request->input('remise', 0);

        // 创建订单主表记录
        $order = RestauCommande::create([
            'numero_commande' => 'CMDE-' . now()->timestamp,
            'date_commande' => now(),
            'made_by' => $request->input('made_by'),
            'sub_total' => $subTotal,
            'grand_total' => $grandTotal,
            'remise' => $request->input('remise', 0)
        ]);

        // 批量写入关联表数据
        $order->produits()->saveMany($orderItems);

        return response()->json([
            'success' => true,
            'order_id' => $order->id,
            'message' => '订单创建成功'
        ]);
    });
}

内容的提问来源于stack exchange,提问作者Derick T.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 15:06:07