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

Laravel实现订单提交按钮禁用:流程完成前禁止重复点击

解决重复下单问题:前端禁用+后端兜底双方案

嘿,这个问题我之前帮好几个开发者踩过坑!用户因为网络慢重复点击导致多订单,确实是电商场景里的高频问题,咱们得从前端体验优化+后端安全兜底两方面入手——只靠前端的话,懂点技术的用户绕过去还是会出问题,双管齐下才稳妥。

一、前端快速拦截:点击后立即禁用按钮

这是最直接的用户体验优化,用户一点击下单按钮,立刻把按钮置灰禁用,同时修改文字提示“提交中...”,从根源上避免重复点击。

原生JS实现(适合纯HTML页面)

假设你的表单ID是order-form,下单按钮ID是order-submit-btn,添加这段脚本:

const submitBtn = document.getElementById('order-submit-btn');
const orderForm = document.getElementById('order-form');

orderForm.addEventListener('submit', function() {
    // 禁用按钮并修改提示文字
    submitBtn.disabled = true;
    submitBtn.textContent = '提交中...';
});

jQuery实现(如果项目用了jQuery)

代码更简洁:

$('#order-submit-btn').on('click', function() {
    $(this).prop('disabled', true).text('提交中...');
    $('#order-form').submit();
});

二、后端兜底:防止恶意/绕过前端的重复提交

前端只是防普通用户,要是有人刻意绕过(比如用Postman重复发请求),还是会生成重复订单,所以必须加后端防重逻辑。这里给你两种实用方案:

方案1:一次性防重令牌(推荐)

在生成下单页面时,生成一个唯一token存在Session里,渲染到表单隐藏字段中。提交时验证token,验证通过就立刻销毁Session里的token,重复提交会因为token不存在而失败。

  1. 先在下单页面的控制器里生成token:
use Illuminate\Support\Str;

public function createOrderPage()
{
    $orderToken = Str::random(40);
    session()->put('order_token', $orderToken);
    return view('order.create', compact('orderToken'));
}
  1. 在Blade表单里添加隐藏字段:
<form id="order-form" method="POST" action="{{ route('order.save') }}">
    @csrf
    <!-- 新增防重token隐藏字段 -->
    <input type="hidden" name="order_token" value="{{ $orderToken }}">
    <!-- 其他商品信息字段 -->
    <button type="submit" id="order-submit-btn">提交订单</button>
</form>
  1. 修改你提供的save方法,添加token验证逻辑:
use Illuminate\Support\Str;
use Illuminate\Http\Request;

public function save(Request $request)
{
    // 验证表单字段+防重token
    $request->validate([
        'order_token' => 'required',
        'name' => 'required',
        'price' => 'required|numeric',
    ]);

    // 取出并销毁Session里的token(确保只能用一次)
    $sessionToken = session()->pull('order_token');
    if ($request->order_token !== $sessionToken) {
        return redirect('admin')->with('error', '请勿重复提交订单');
    }

    // 创建订单(注意:你原来的代码漏了save()方法,必须调用才会存入数据库!)
    $food = new Food([
        'name' => $request->get('name'),
        'price' => $request->get('price'),
    ]);
    $food->save();

    return redirect('admin')->with('status','Order successfully placed');
}

方案2:时间窗口+数据库重复检查

如果是同一个用户短时间内提交相同商品的订单,你可以检查最近N分钟内是否有重复订单:

use Illuminate\Http\Request;

public function save(Request $request)
{
    // 假设你的订单表关联了用户,检查当前用户5分钟内是否提交过相同商品
    $hasRecentOrder = Food::where('user_id', auth()->id())
        ->where('name', $request->get('name'))
        ->where('created_at', '>=', now()->subMinutes(5))
        ->exists();

    if ($hasRecentOrder) {
        return redirect('admin')->with('error', '您刚刚提交过相同订单,请稍后再试');
    }

    $food = new Food([
        'user_id' => auth()->id(),
        'name' => $request->get('name'),
        'price' => $request->get('price'),
    ]);
    $food->save();

    return redirect('admin')->with('status','Order successfully placed');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:17:03