Bil*_*ood 2 php concurrency laravel laravel-session
在 Laravel 中,有什么方法可以停止同时与同一条记录交互。例如,如果用户 A 正在编辑一条记录,那么我同时需要阻止用户 B 编辑同一条记录。
注意:我使用的是 SESSION_DRIVER=file & Laravel 5.2
目前大约有 500 多名用户使用该系统,它是一种管理面板,管理员可以在其中与记录交互,但我需要停止并发访问。最佳解决方案是什么?
这是我如何实现这一目标的。
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