В Laravel есть какой-нибудь способ прекратить взаимодействие с одной и той же записью одновременно. Например, если пользователь A редактирует запись, то в то же время мне нужно запретить пользователю B редактировать ту же запись.
Примечание: я использую SESSION_DRIVER = файл & Ларавел 5.2
В настоящее время системой пользуются более 500 пользователей, и это своего рода панель администратора, где администраторы взаимодействуют с записями, но мне нужно прекратить одновременный доступ. что было бы оптимальным решением.
Я недавно реализовал нечто подобное.
Для каждой рассматриваемой таблицы добавьте столбец с именем «lock» типа «dateTime» следующим образом:
$table->dateTime('lock')->nullable();
Теперь перейдите к контроллеру и найдите метод «edit». Здесь вы должны проверить, установлен ли «замок». Если это так, вы должны проверить, если он старше, скажем, 15 минут (это важно, потому что, если пользователь закрывает страницу без обновления записи, она будет заблокирована навсегда). Это может быть закодировано следующим образом:
$sample = $this->sampleRepository->getById($idsample);
if (!$sample->lock || (strtotime($sample->lock) < strtotime('-15minutes'))) {
// Ok he can access the record
} else {
// He can not access the record
}
Если у пользователя есть доступ к записи, вы должны обновить «блокировку», чтобы никто другой не мог получить к ней доступ.
if (!$sample->lock || (strtotime($sample->lock) < strtotime('-15minutes'))) {
// Ok he can access the record
$sample->lock = \Carbon\Carbon::now();
$sample->save();
// Return view, etc.
} else ...
Теперь давайте посмотрим на метод «обновления». После обновления записи вы хотите сбросить «блокировку», чтобы следующий пользователь мог снова редактировать запись. Просто добавьте эту строку и обновите запись как обычно:
$sample->lock = null;
Теперь только один пользователь может редактировать запись одновременно.
Вы также можете создать метод «принудительной разблокировки», с помощью которого пользователь может сбросить «блокировку» без необходимости ждать 15 минут.
Это простая реализация. Это лучше работает с JavaScript, потому что вы можете проверить в режиме реального времени, если кто-то редактирует запись.
Вам нужно добавить столбец с именем как editing
в ваши таблицы и соответствующий атрибут модели.
проверить, еслиediting
является false
затем позвольте пользователю редактировать.
В любом редактировании пользователя измените его значение на true,
Вот как я могу этого добиться.
1) Создайте миграцию, чтобы добавить 2 столбца в модель is_editing
а также editing_by
а также updated_at
(нет необходимости создавать updated_at
если уже есть)
2) Сделать промежуточное ПО php artisan make:middleware StopConcurrentOperations
,
3) Зарегистрируйте промежуточное ПО в app/Http/Kernel.php
под $routeMiddleware
,
4) Применить промежуточное программное обеспечение к контроллеру
$this->middleware('concurrent.operations',["only"=>["edit","update"]]);
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);
}
}
здесь я проверяю, редактировал ли кто-либо запись, и проверял время, когда редактирование выполнялось.
6) Опционально на стороне клиента, если пользователь, выполняющий редактирование, закрывает окна, чтобы разблокировать запись, как
window.onbeforeunload = function() {
var url = "{{route('unlock_route_name',$operation->id)}}";
$.ajax({ url: url, method: 'post' })
};
чтобы завершить процесс со стороны клиента, вы должны создать маршрут и метод в контроллере и просто разблокировать запись как
$operation = Operation::findOrFail($id);
$activity = $operation->activities()->where("is_editing",true)->first();
$activity->is_editing = false;
$activity->save();
Примечание: в моем примере у меня есть другая таблица для регистрации активаций alerady OperationActivity
и скорее всего модель зовут Operation
Я сделал то же самое, но когда пользователь отправлял «пут», сначала проверил, не были ли данные кем-то изменены одновременно, если нет — обновите, еще раз вернув информацию и новые данные.
Вы можете проверить только дату обновления или проверить все данные.