Гейти (gates) - замикання для дій, не прив'язаних до конкретної моделі:
// AppServiceProvider::boot()
Gate::define('view-reports', fn (User $user) => $user->hasRole('analyst'));
Gate::define('access-admin', fn (User $user) => $user->is_admin);
Політики (policies) - клас з правилами для однієї моделі:
php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->id === $post->author_id;
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->author_id || $user->is_moderator;
}
}
Laravel знаходить політику за назвою (App\Models\Post → App\Policies\PostPolicy) або за атрибутом на моделі.
Як перевіряти:
// у контролері
Gate::authorize('update', $post); // 403, якщо заборонено
if ($request->user()->cannot('delete', $post)) { abort(403); }
// у Blade - лише для відображення
@can('update', $post) <a href="...">Редагувати</a> @endcan
// у Form Request
public function authorize(): bool { return $this->user()->can('update', $this->route('post')); }
На маршрутах - middleware can:
Route::put('/posts/{post}', [PostController::class, 'update'])->can('update', 'post');
Route::get('/admin/reports', ReportController::class)->middleware('can:view-reports');
Route::post('/posts', [PostController::class, 'store'])->can('create', Post::class);
'post' - назва параметра маршруту: після прив'язки моделі в політику потрапить конкретний пост. Для дій без екземпляра (create) передається клас.
Що обрати:
- політика - для всього, що стосується моделі (CRUD і власні дії). Логіка доступу до сутності - в одному місці;
- гейт - для загальних можливостей (доступ до адмінки, звітів, функцій тарифу).
Пастки:
@canу шаблоні лише ховає кнопку - перевірка на сервері (контролер, маршрут) обов'язкова;- методи політики повинні повертати
bool(абоResponse): забутийreturnдаєnull- і доступ заборонено, що безпечно, але збиває з пантелику; - гості: для неавтентифікованого користувача гейти й політики за замовчуванням повертають
false, якщо параметр користувача не оголошено як?User.
Докладніше в документації: Laravel: авторизація через middleware