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

Laravel中如何防止管理员同时编辑同一客户资料(低负载)

Laravel实现客户资料编辑锁定(低负载最优方案)

这是一种低负载的实现方案,核心用数据库字段标记锁定状态+超时自动释放,避免额外缓存或分布式锁带来的服务器开销,具体步骤如下:

1. 给客户表添加锁定字段

先给customers表新增两个字段,用来记录锁定的管理员和锁定时间:

// 生成迁移文件后编辑内容
Schema::table('customers', function (Blueprint $table) {
    $table->unsignedBigInteger('locked_by')->nullable(); // 锁定者ID
    $table->timestamp('locked_at')->nullable(); // 锁定时间
    // 可选:关联管理员表外键,删除管理员时自动清空锁定记录
    $table->foreign('locked_by')->references('id')->on('admins')->onDelete('set null');
});

执行迁移:php artisan migrate

2. 编辑页的锁定校验逻辑

打开客户编辑页时,先检查该客户是否被其他管理员有效锁定:

public function edit(Customer $customer)
{
    $lockTimeout = now()->subMinutes(5); // 设置5分钟超时,可根据需求调整
    // 校验:如果被其他管理员锁定且未超时,返回错误
    if ($customer->locked_by && $customer->locked_at > $lockTimeout && $customer->locked_by !== auth()->id()) {
        $lockingAdmin = Admin::find($customer->locked_by);
        return back()->withErrors([
            'lock' => "该客户正在被{$lockingAdmin->name}编辑,请稍后再试"
        ]);
    }

    // 刷新/设置锁定状态(自己锁定或锁已超时的情况)
    $customer->update([
        'locked_by' => auth()->id(),
        'locked_at' => now()
    ]);

    return view('customers.edit', compact('customer'));
}

3. 保存/取消编辑时释放锁定

当管理员完成编辑或主动取消时,释放锁定;同时校验只有锁定者才能修改:

// 保存更新方法
public function update(UpdateCustomerRequest $request, Customer $customer)
{
    $lockTimeout = now()->subMinutes(5);
    // 校验:非锁定者且锁未超时,禁止修改
    if ($customer->locked_by !== auth()->id() && $customer->locked_at > $lockTimeout) {
        return back()->withErrors(['lock' => '你无权编辑该客户,当前客户正在被他人编辑']);
    }

    // 更新客户资料
    $customer->update($request->validated());

    // 释放锁定
    $customer->update([
        'locked_by' => null,
        'locked_at' => null
    ]);

    return redirect()->route('customers.index')->with('success', '客户资料更新成功');
}

// 主动取消编辑的解锁方法
public function unlock(Customer $customer)
{
    if ($customer->locked_by === auth()->id()) {
        $customer->update([
            'locked_by' => null,
            'locked_at' => null
        ]);
    }
    return back();
}

4. 前端辅助优化(进一步降低无效请求)

  • 定时刷新锁定时间:避免管理员长时间停留在编辑页导致锁超时,1分钟一次AJAX请求即可
  • 页面关闭时尝试解锁:用beforeunload事件发送请求,配合keepalive确保请求能发出(兜底还是靠超时机制)

前端JS示例:

// 定时刷新锁定(1分钟一次)
setInterval(() => {
    fetch(`/customers/{{ $customer->id }}/refresh-lock`, {
        method: 'POST',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
        }
    });
}, 60000);

// 页面关闭时尝试解锁
window.addEventListener('beforeunload', () => {
    fetch(`/customers/{{ $customer->id }}/unlock`, {
        method: 'POST',
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
        },
        keepalive: true
    });
});

对应的路由和控制器方法:

// routes/web.php
Route::post('/customers/{customer}/refresh-lock', [CustomerController::class, 'refreshLock']);

// 控制器新增方法
public function refreshLock(Customer $customer)
{
    if ($customer->locked_by === auth()->id()) {
        $customer->update(['locked_at' => now()]);
    }
    return response()->noContent();
}

方案优势

  • 极低服务器负载:仅在编辑页打开、保存、定时刷新时操作数据库,都是单条记录的简单读写
  • 无永久锁定风险:超时机制自动释放异常情况(比如管理员直接关浏览器)的锁定,无需额外后台清理任务
  • 逻辑简单可靠:不需要依赖缓存、分布式锁等复杂组件,维护成本低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:40:35