GUÍA COMPLETA DE LARAVEL GATE: AUTORIZACIÓN AVANZADA
Gate es el sistema de autorización basado en closures, funciones, que Laravel ofrece para determinar si un usuario tiene permiso para realizar una acción específica.
Mientras que las Policies están orientadas a un modelo Eloquent, los Gates son más flexibles y se usan para permisos que no están directamente relacionados con un modelo o que son más complejos: acciones globales, reportes, etc..
Diferencia entre Gates y Policies
Cómo definir Gates
Los Gates se definen normalmente en el fichero "AuthServiceProvider"// app/Providers/AuthServiceProvider.php
public function boot(): void
{
Gate::define('editar-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
Gate::define('publicar-post', function (User $user) {
return $user->hasRole('editor') || $user->hasRole('admin');
});
Gate::define('ver-reporte-financiero', function (User $user) {
return $user->canAccessFinancialReports();
});
}
Gates con parámetros adicionales
Gate::define('actualizar-imagen', function (User $user, Post $post, string $tipo) {
if ($tipo === 'portada' && !$user->esPremium()) {
return false;
}
return $user->id === $post->user_id || $user->esAdmin();
});
Métodos importantes de Gate
// Verificar permiso
if (Gate::allows('editar-post', $post)) {
// Puede editar
}
if (Gate::denies('publicar-post')) {
abort(403);
}
// Con usuario específico
if (Gate::forUser($otroUsuario)->allows('editar-post', $post)) { ... }
// Comprobar varios al mismo tiempo
Gate::any(['editar-post', 'publicar-post'], $post);
Gate::none(['eliminar-post', 'ocultar-post'], $post);
before() y after() – Hooks globales
Son muy útiles para lógica centralizada (por ejemplo, super admins):Gate::before(function (User $user, string $ability) {
if ($user->esSuperAdmin()) {
return true; // Puede hacer TODO
}
// null = continuar con la validación normal
});
Gate::after(function (User $user, string $ability, bool $result, $arguments) {
// Registrar intentos de acceso, auditoría, etc.
Log::info("Usuario {$user->id} intentó {$ability}: " . ($result ? 'OK' : 'DENEGADO'));
});
Uso en Controladores
public function update(Request $request, Post $post)
{
$this->authorize('editar-post', $post); // Lanza 403 automáticamente
// O manualmente
Gate::authorize('editar-post', $post);
// ...
}
En Blade (Vistas)
@can('editar-post', $post)
Editar
@endcan
@cannot('publicar-post')
No tienes permiso para publicar.
@endcannot
@canany(['editar-post', 'eliminar-post'], $post)
@endcanany
Gates en rutas (Middleware)
Route::middleware('can:ver-reporte-financiero')->group(function () {
Route::get('/reportes/financieros', [ReporteController::class, 'financieros']);
});
Ejemplo Real: Sistema de Contenidos
Gate::define('gestionar-contenido', function (User $user) {
return $user->hasAnyRole(['admin', 'editor', 'moderador']);
});
Gate::define('aprobar-comentario', function (User $user, Comment $comment) {
return $user->hasRole('moderador') ||
($user->hasRole('editor') && $comment->post->author_id === $user->id);
});