Laravel - 停止并发访问记录

Bil*_*ood 2 php concurrency laravel laravel-session

在 Laravel 中,有什么方法可以停止同时与同一条记录交互。例如,如果用户 A 正在编辑一条记录,那么我同时需要阻止用户 B 编辑同一条记录。

注意:我使用的是 SESSION_DRIVER=file & Laravel 5.2

目前大约有 500 多名用户使用该系统,它是一种管理面板,管理员可以在其中与记录交互,但我需要停止并发访问。最佳解决方案是什么?

Bil*_*ood 5

这是我如何实现这一目标的。

1) 创建迁移以在模型中添加 2 列is_editing并且(如果已经存在,则editing_by无需updated_at 创建)updated_at

2)制作中间件php artisan make:middleware StopConcurrentOperations

app/Http/Kernel.php3)在下面注册中间件$routeMiddleware

4) 将中间件应用到控制器

$this->middleware('concurrent.operations',["only"=>["edit","update"]]);
Run Code Online (Sandbox Code Playgroud)

5) 阻止中间件中的并发编辑

<?php

namespace App\Http\Middleware;

use App\OperationActivity;
use Carbon\Carbon;
use Closure;
use Illuminate\Support\Facades\Auth;

class StopConcurrentOperations
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        $operation_id = current($request->route()->parameters());
        $user_id = Auth::guard('admin')->user()->id;
        if(Auth::guard('admin')->user() && !empty($operation_id)){
            $activity = OperationActivity::firstOrNew(["operation_id" => $operation_id]);
            if($activity->is_editing && $activity->updated_at->diffInMinutes(Carbon::now())<5 && $activity->editing_by!=$user_id)
                abort(409);
            else {
                $activity->is_editing = true;
                $activity->editing_by = $user_id;
                $activity->save();
            }
        }
        return $next($request);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里我检查是否有人已经编辑记录并检查执行编辑的时间。

6) 如果编辑用户关闭窗口,则可以选择在客户端,然后取消阻止记录,例如

  window.onbeforeunload = function() {
    var url = "{{route('unlock_route_name',$operation->id)}}";
    $.ajax({ url: url, method: 'post' })
  };
Run Code Online (Sandbox Code Playgroud)

要从客户端完成该过程,您必须在控制器中创建一个路由和一个方法,然后解锁记录,例如

      $operation = Operation::findOrFail($id);
      $activity = $operation->activities()->where("is_editing",true)->first();
      $activity->is_editing = false;
      $activity->save();
Run Code Online (Sandbox Code Playgroud)

注意:在我的示例中,我有不同的表来记录活动OperationActivity,可能的模型名称是Operation