Enrutamiento
Rutas Básicas
Las rutas más básicas de Laravel aceptan un URI y un closure, proporcionando un método muy simple y expresivo de definir rutas y comportamientos sin archivos de configuración de rutas complicados:
use Illuminate\Support\Facades\Route;
Route::get('/greeting', function () {
return 'Hello World';
});
Los Archivos de Ruta Predeterminados
Todas las rutas de Laravel se definen en tus archivos de ruta, que se encuentran en el directorio routes
. Estos archivos son cargados automáticamente por Laravel usando la configuración especificada en el archivo bootstrap/app.php
de tu aplicación. El archivo routes/web.php
define rutas que son para tu interfaz web. Estas rutas se asignan al grupo de middleware web
, que proporciona características como el estado de la sesión y la protección CSRF.
Para la mayoría de las aplicaciones, comenzarás definiendo rutas en tu archivo routes/web.php
. Las rutas definidas en routes/web.php
pueden ser accedidas ingresando la URL de la ruta definida en tu navegador. Por ejemplo, puedes acceder a la siguiente ruta navegando a http://example.com/user
en tu navegador:
use App\Http\Controllers\UserController;
Route::get('/user', [UserController::class, 'index']);
Rutas API
Si tu aplicación también ofrecerá una API sin estado, puedes habilitar el enrutamiento API usando el comando Artisan install:api
:
php artisan install:api
El comando install:api
instala Laravel Sanctum, que proporciona un guard de autenticación de token API robusto pero simple que puede ser usado para autenticar consumidores de API de terceros, SPAs o aplicaciones móviles. Además, el comando install:api
crea el archivo routes/api.php
:
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Las rutas en routes/api.php
son sin estado y se asignan al grupo de middleware api
. Además, el prefijo URI /api
se aplica automáticamente a estas rutas, por lo que no necesitas aplicarlo manualmente a cada ruta en el archivo. Puedes cambiar el prefijo modificando el archivo bootstrap/app.php
de tu aplicación:
->withRouting(
api: __DIR__.'/../routes/api.php',
apiPrefix: 'api/admin',
// ...
)
Métodos Disponibles del Enrutador
El enrutador te permite registrar rutas que responden a cualquier verbo HTTP:
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
A veces puede que necesites registrar una ruta que responda a múltiples verbos HTTP. Puedes hacerlo usando el método match
. O, incluso puedes registrar una ruta que responda a todos los verbos HTTP usando el método any
:
Route::match(['get', 'post'], '/', function () {
// ...
});
Route::any('/', function () {
// ...
});
Al definir múltiples rutas que comparten el mismo URI, las rutas que usan los métodos get
, post
, put
, patch
, delete
y options
deben definirse antes de las rutas que usan los métodos any
, match
y redirect
. Esto asegura que la solicitud entrante se empareje con la ruta correcta.
Inyección de Dependencias
Puedes declarar cualquier dependencia requerida por tu ruta en la firma del callback de tu ruta. Las dependencias declaradas se resolverán e inyectarán automáticamente en el callback por el contenedor de servicios de Laravel. Por ejemplo, puedes declarar la clase Illuminate\Http\Request
para que la solicitud HTTP actual se inyecte automáticamente en el callback de tu ruta:
use Illuminate\Http\Request;
Route::get('/users', function (Request $request) {
// ...
});
Protección CSRF
Recuerda, cualquier formulario HTML que apunte a rutas POST
, PUT
, PATCH
o DELETE
que estén definidas en el archivo de rutas web debe incluir un campo de token CSRF. De lo contrario, la solicitud será rechazada. Puedes leer más sobre la protección CSRF en la documentación de CSRF:
<form method="POST" action="/profile">
@csrf
...
</form>
Rutas de Redirección
Si estás definiendo una ruta que redirige a otro URI, puedes usar el método Route::redirect
. Este método proporciona un atajo conveniente para que no tengas que definir una ruta completa o un controlador para realizar una redirección simple:
Route::redirect('/here', '/there');
Por defecto, Route::redirect
devuelve un código de estado 302. Puedes personalizar el código de estado usando el tercer parámetro opcional:
Route::redirect('/here', '/there', 301);
O, puedes usar el método Route::permanentRedirect
para devolver un código de estado 301:
Route::permanentRedirect('/here', '/there');
Al usar parámetros de ruta en rutas de redirección, los siguientes parámetros están reservados por Laravel y no pueden ser usados: destination
y status
.
Rutas de Vista
Si tu ruta solo necesita devolver una vista, puedes usar el método Route::view
. Al igual que el método redirect
, este método proporciona un atajo simple para que no tengas que definir una ruta completa o un controlador. El método view
acepta un URI como su primer argumento y un nombre de vista como su segundo argumento. Además, puedes proporcionar un array de datos para pasar a la vista como un tercer argumento opcional:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
Al usar parámetros de ruta en rutas de vista, los siguientes parámetros están reservados por Laravel y no pueden ser usados: view
, data
, status
y headers
.
Listando Tus Rutas
El comando Artisan route:list
puede proporcionar fácilmente una visión general de todas las rutas que están definidas por tu aplicación:
php artisan route:list
Por defecto, el middleware de ruta que se asigna a cada ruta no se mostrará en la salida de route:list
; sin embargo, puedes instruir a Laravel para que muestre el middleware de ruta y los nombres de los grupos de middleware agregando la opción -v
al comando:
php artisan route:list -v
# Expandir grupos de middleware...
php artisan route:list -vv
También puedes instruir a Laravel para que solo muestre las rutas que comienzan con un URI dado:
php artisan route:list --path=api
Además, puedes instruir a Laravel para que oculte cualquier ruta que esté definida por paquetes de terceros proporcionando la opción --except-vendor
al ejecutar el comando route:list
:
php artisan route:list --except-vendor
De igual manera, también puedes instruir a Laravel para que solo muestre las rutas que están definidas por paquetes de terceros proporcionando la opción --only-vendor
al ejecutar el comando route:list
:
php artisan route:list --only-vendor
Personalización del Enrutamiento
Por defecto, las rutas de tu aplicación están configuradas y cargadas por el archivo bootstrap/app.php
:
<?php
use Illuminate\Foundation\Application;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)->create();
Sin embargo, a veces puede que quieras definir un archivo completamente nuevo para contener un subconjunto de las rutas de tu aplicación. Para lograr esto, puedes proporcionar un closure then
al método withRouting
. Dentro de este closure, puedes registrar cualquier ruta adicional que sea necesaria para tu aplicación:
use Illuminate\Support\Facades\Route;
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('api')
->prefix('webhooks')
->name('webhooks.')
->group(base_path('routes/webhooks.php'));
},
)
O, incluso puedes tomar el control completo sobre el registro de rutas proporcionando un closure using
al método withRouting
. Cuando se pasa este argumento, el framework no registrará ninguna ruta HTTP y tú serás responsable de registrar manualmente todas las rutas:
use Illuminate\Support\Facades\Route;
->withRouting(
commands: __DIR__.'/../routes/console.php',
using: function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
},
)
Parámetros de Ruta
Parámetros Requeridos
A veces necesitarás capturar segmentos del URI dentro de tu ruta. Por ejemplo, puede que necesites capturar el ID de un usuario desde la URL. Puedes hacerlo definiendo parámetros de ruta:
Route::get('/user/{id}', function (string $id) {
return 'User '.$id;
});
Puedes definir tantos parámetros de ruta como necesite tu ruta:
Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});
Los parámetros de ruta siempre están encerrados dentro de llaves {}
y deben consistir en caracteres alfabéticos. Los guiones bajos _
también son aceptables dentro de los nombres de los parámetros de ruta. Los parámetros de ruta se inyectan en los callbacks/controladores de ruta según su orden; los nombres de los argumentos del callback/controlador de ruta no importan.
Parámetros y Inyección de Dependencias
Si tu ruta tiene dependencias que te gustaría que el contenedor de servicios de Laravel inyectara automáticamente en el callback de tu ruta, debes listar tus parámetros de ruta después de tus dependencias:
use Illuminate\Http\Request;
Route::get('/user/{id}', function (Request $request, string $id) {
return 'User '.$id;
});
Parámetros Opcionales
Ocasionalmente, puede que necesites especificar un parámetro de ruta que no siempre esté presente en el URI. Puedes hacerlo colocando un signo de interrogación ?
después del nombre del parámetro. Asegúrate de darle a la variable correspondiente de la ruta un valor por defecto:
Route::get('/user/{name?}', function (?string $name = null) {
return $name;
});
Route::get('/user/{name?}', function (?string $name = 'John') {
return $name;
});
Restricciones de Expresiones Regulares
Puedes restringir el formato de tus parámetros de ruta usando el método where
en una instancia de ruta. El método where
acepta el nombre del parámetro y una expresión regular que define cómo debe ser restringido el parámetro:
Route::get('/user/{name}', function (string $name) {
// ...
})->where('name', '[A-Za-z]+');
Route::get('/user/{id}', function (string $id) {
// ...
})->where('id', '[0-9]+');
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
Para mayor comodidad, algunos patrones de expresiones regulares comúnmente usados tienen métodos helper que te permiten agregar rápidamente restricciones de patrones a tus rutas:
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function (string $name) {
// ...
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUuid('id');
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUlid('id');
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', ['movie', 'song', 'painting']);
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', CategoryEnum::cases());
Si la solicitud entrante no coincide con las restricciones del patrón de la ruta, se devolverá una respuesta HTTP 404.
Restricciones Globales
Si deseas que un parámetro de ruta siempre esté restringido por una expresión regular dada, puedes usar el método pattern
. Debes definir estos patrones en el método boot
de la clase App\Providers\AppServiceProvider
de tu aplicación:
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}
Una vez que el patrón ha sido definido, se aplica automáticamente a todas las rutas que usan ese nombre de parámetro:
Route::get('/user/{id}', function (string $id) {
// Solo se ejecuta si {id} es numérico...
});
Barras Inclinadas Codificadas
El componente de enrutamiento de Laravel permite que todos los caracteres excepto /
estén presentes dentro de los valores de los parámetros de ruta. Debes permitir explícitamente que /
sea parte de tu marcador de posición usando una expresión regular en la condición where
:
Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');
Las barras inclinadas codificadas solo son compatibles dentro del último segmento de la ruta.
Rutas Nombradas
Las rutas nombradas permiten la generación conveniente de URLs o redirecciones para rutas específicas. Puedes especificar un nombre para una ruta encadenando el método name
a la definición de la ruta:
Route::get('/user/profile', function () {
// ...
})->name('profile');
También puedes especificar nombres de ruta para acciones de controladores:
Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
Los nombres de ruta siempre deben ser únicos.
Generando URLs para Rutas Nombradas
Una vez que hayas asignado un nombre a una ruta dada, puedes usar el nombre de la ruta al generar URLs o redirecciones a través de las funciones helper route
y redirect
de Laravel:
// Generando URLs...
$url = route('profile');
// Generando Redirecciones...
return redirect()->route('profile');
return to_route('profile');
Si la ruta nombrada define parámetros, puedes pasar los parámetros como el segundo argumento a la función route
. Los parámetros dados se insertarán automáticamente en la URL generada en sus posiciones correctas:
Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
$url = route('profile', ['id' => 1]);
Si pasas parámetros adicionales en el array, esos pares clave/valor se agregarán automáticamente a la cadena de consulta de la URL generada:
Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
// /user/1/profile?photos=yes
A veces, puede que desees especificar valores predeterminados para los parámetros de URL en toda la solicitud, como la configuración regional actual. Para lograr esto, puedes usar el método URL::defaults
.
Inspeccionando la Ruta Actual
Si deseas determinar si la solicitud actual fue dirigida a una ruta nombrada dada, puedes usar el método named
en una instancia de Route
. Por ejemplo, puedes verificar el nombre de la ruta actual desde un middleware de ruta:
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Maneja una solicitud entrante.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->route()->named('profile')) {
// ...
}
return $next($request);
}
Grupos de Rutas
Los grupos de rutas te permiten compartir atributos de ruta, como middleware, a través de un gran número de rutas sin necesidad de definir esos atributos en cada ruta individual.
Los grupos anidados intentan «fusionar» inteligentemente los atributos con su grupo padre. Los middleware y las condiciones where
se fusionan mientras que los nombres y los prefijos se agregan. Los delimitadores de espacio de nombres y las barras en los prefijos de URI se agregan automáticamente donde sea apropiado.
Middleware
Para asignar middleware a todas las rutas dentro de un grupo, puedes usar el método middleware
antes de definir el grupo. Los middleware se ejecutan en el orden en que están listados en el array:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Usa los middleware first & second...
});
Route::get('/user/profile', function () {
// Usa los middleware first & second...
});
});
Controladores
Si un grupo de rutas utiliza el mismo controlador, puedes usar el método controller
para definir el controlador común para todas las rutas dentro del grupo. Luego, al definir las rutas, solo necesitas proporcionar el método del controlador que invocan:
use App\Http\Controllers\OrderController;
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});
Enrutamiento de Subdominios
Los grupos de rutas también pueden ser usados para manejar el enrutamiento de subdominios. Los subdominios pueden asignarse a parámetros de ruta al igual que los URIs de ruta, permitiéndote capturar una porción del subdominio para su uso en tu ruta o controlador. El subdominio puede ser especificado llamando al método domain
antes de definir el grupo:
Route::domain('{account}.example.com')->group(function () {
Route::get('/user/{id}', function (string $account, string $id) {
// ...
});
});
Para asegurar que tus rutas de subdominio sean accesibles, debes registrar las rutas de subdominio antes de registrar las rutas del dominio raíz. Esto evitará que las rutas del dominio raíz sobrescriban las rutas de subdominio que tienen el mismo camino de URI.
Prefijos de Ruta
El método prefix
puede ser usado para prefijar cada ruta en el grupo con un URI dado. Por ejemplo, puede que desees prefijar todos los URIs de ruta dentro del grupo con admin
:
Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Coincide con la URL "/admin/users"
});
});
Prefijos de Nombre de Ruta
El método name
puede ser usado para prefijar cada nombre de ruta en el grupo con una cadena dada. Por ejemplo, puede que desees prefijar los nombres de todas las rutas en el grupo con admin
. La cadena dada se prefija al nombre de la ruta exactamente como se especifica, por lo que nos aseguraremos de proporcionar el carácter .
al final del prefijo:
Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Ruta asignada con el nombre "admin.users"...
})->name('users');
});
Enlace de Modelo de Ruta
Al inyectar un ID de modelo en una ruta o acción de controlador, a menudo consultarás la base de datos para recuperar el modelo que corresponde a ese ID. El enlace de modelo de ruta de Laravel proporciona una forma conveniente de inyectar automáticamente las instancias del modelo directamente en tus rutas. Por ejemplo, en lugar de inyectar el ID de un usuario, puedes inyectar la instancia completa del modelo User
que coincide con el ID dado.
Enlace Implícito
Laravel resuelve automáticamente los modelos Eloquent definidos en rutas o acciones de controlador cuyos nombres de variables con tipo coinciden con un segmento de ruta. Por ejemplo:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
Dado que la variable $user
tiene el tipo App\Models\User
y el nombre de la variable coincide con el segmento {user}
del URI, Laravel inyectará automáticamente la instancia del modelo que tiene un ID que coincide con el valor correspondiente del URI de la solicitud. Si no se encuentra una instancia de modelo coincidente en la base de datos, se generará automáticamente una respuesta HTTP 404.
Por supuesto, el enlace implícito también es posible cuando se usan métodos de controlador. Nuevamente, ten en cuenta que el segmento {user}
del URI coincide con la variable $user
en el controlador que contiene un tipo App\Models\User
:
use App\Http\Controllers\UserController;
use App\Models\User;
// Definición de ruta...
Route::get('/users/{user}', [UserController::class, 'show']);
// Definición del método del controlador...
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}
Modelos con Eliminación Suave
Típicamente, el enlace implícito de modelo no recuperará modelos que han sido eliminados suavemente. Sin embargo, puedes instruir al enlace implícito para que recupere estos modelos encadenando el método withTrashed
a la definición de tu ruta:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
})->withTrashed();
Personalizando la Clave
A veces puede que desees resolver modelos Eloquent usando una columna diferente a id
. Para hacerlo, puedes especificar la columna en la definición del parámetro de ruta:
use App\Models\Post;
Route::get('/posts/{post:slug}', function (Post $post) {
return $post;
});
Si deseas que el enlace de modelo siempre use una columna de base de datos diferente a id
al recuperar una clase de modelo dada, puedes sobrescribir el método getRouteKeyName
en el modelo Eloquent:
/**
* Obtiene la clave de ruta para el modelo.
*/
public function getRouteKeyName(): string
{
return 'slug';
}
Claves Personalizadas y Alcance
Al enlazar implícitamente múltiples modelos Eloquent en una sola definición de ruta, puede que desees limitar el segundo modelo Eloquent de manera que deba ser un hijo del modelo Eloquent anterior. Por ejemplo, considera esta definición de ruta que recupera una publicación de blog por slug
para un usuario específico:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
Al usar un enlace implícito con clave personalizada como un parámetro de ruta anidado, Laravel limitará automáticamente la consulta para recuperar el modelo anidado por su padre usando convenciones para adivinar el nombre de la relación en el padre. En este caso, se asumirá que el modelo User
tiene una relación llamada posts
(la forma plural del nombre del parámetro de ruta) que puede ser usada para recuperar el modelo Post
.
Si lo deseas, puedes instruir a Laravel para que limite los enlaces «hijos» incluso cuando no se proporciona una clave personalizada. Para hacerlo, puedes invocar el método scopeBindings
al definir tu ruta:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();
O, puedes instruir a un grupo completo de definiciones de ruta para que usen enlaces limitados:
Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});
De manera similar, puedes instruir explícitamente a Laravel para que no limite los enlaces invocando el método withoutScopedBindings
:
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();
Personalizando el Comportamiento de Modelos Faltantes
Típicamente, se generará una respuesta HTTP 404 si no se encuentra un modelo enlazado implícitamente. Sin embargo, puedes personalizar este comportamiento llamando al método missing
al definir tu ruta. El método missing
acepta un closure que será invocado si no se puede encontrar un modelo enlazado implícitamente:
use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
->name('locations.view')
->missing(function (Request $request) {
return Redirect::route('locations.index');
});
Enlace Implícito de Enum
PHP 8.1 introdujo soporte para Enums. Para complementar esta característica, Laravel te permite declarar un Enum respaldado en la definición de tu ruta y Laravel solo invocará la ruta si ese segmento de ruta corresponde a un valor válido del Enum. De lo contrario, se devolverá automáticamente una respuesta HTTP 404. Por ejemplo, dado el siguiente Enum:
<?php
namespace App\Enums;
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
Puedes definir una ruta que solo se invocará si el segmento de ruta {category}
es fruits
o people
. De lo contrario, Laravel devolverá una respuesta HTTP 404:
use App\Enums\Category;
use Illuminate\Support\Facades\Route;
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
Enlace Explícito
No estás obligado a usar la resolución de modelo implícita basada en convenciones de Laravel para usar el enlace de modelo. También puedes definir explícitamente cómo los parámetros de ruta corresponden a los modelos. Para registrar un enlace explícito, usa el método model
del enrutador para especificar la clase para un parámetro dado. Debes definir tus enlaces de modelo explícitos al comienzo del método boot
de tu clase AppServiceProvider
:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::model('user', User::class);
}
A continuación, define una ruta que contenga un parámetro {user}
:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
// ...
});
Dado que hemos enlazado todos los parámetros {user}
al modelo App\Models\User
, se inyectará una instancia de esa clase en la ruta. Así, por ejemplo, una solicitud a users/1
inyectará la instancia de User
de la base de datos que tiene un ID de 1.
Si no se encuentra una instancia de modelo coincidente en la base de datos, se generará automáticamente una respuesta HTTP 404.
Personalizando la Lógica de Resolución
Si deseas definir tu propia lógica de resolución de enlace de modelo, puedes usar el método Route::bind
. El closure que pases al método bind
recibirá el valor del segmento del URI y debe devolver la instancia de la clase que debe ser inyectada en la ruta. Nuevamente, esta personalización debe realizarse en el método boot
de tu AppServiceProvider
:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
}
Alternativamente, puedes sobrescribir el método resolveRouteBinding
en tu modelo Eloquent. Este método recibirá el valor del segmento del URI y debe devolver la instancia de la clase que debe ser inyectada en la ruta:
/**
* Recupera el modelo para un valor enlazado.
*
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where('name', $value)->firstOrFail();
}
Si una ruta está utilizando el alcance de enlace implícito, se usará el método resolveChildRouteBinding
para resolver el enlace del hijo del modelo padre:
/**
* Recupera el modelo hijo para un valor enlazado.
*
* @param string $childType
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveChildRouteBinding($childType, $value, $field)
{
return parent::resolveChildRouteBinding($childType, $value, $field);
}
Rutas de Fallback
Usando el método Route::fallback
, puedes definir una ruta que se ejecutará cuando ninguna otra ruta coincida con la solicitud entrante. Típicamente, las solicitudes no manejadas renderizarán automáticamente una página «404» a través del manejador de excepciones de tu aplicación. Sin embargo, dado que normalmente definirías la ruta de fallback dentro de tu archivo routes/web.php
, todo el middleware en el grupo de middleware web
se aplicará a la ruta. Eres libre de agregar middleware adicionales a esta ruta según sea necesario:
Route::fallback(function () {
// ...
});
La ruta de fallback siempre debe ser la última ruta registrada por tu aplicación.
Limitación de Tasa
Definiendo Limitadores de Tasa
Laravel incluye servicios de limitación de tasa poderosos y personalizables que puedes utilizar para restringir la cantidad de tráfico para una ruta o grupo de rutas dado. Para comenzar, debes definir configuraciones de limitador de tasa que satisfagan las necesidades de tu aplicación.
Los limitadores de tasa pueden ser definidos dentro del método boot
de tu clase App\Providers\AppServiceProvider
:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
Los limitadores de tasa se definen usando el método for
de la facade RateLimiter
. El método for
acepta un nombre de limitador de tasa y un closure que devuelve la configuración del límite que debe aplicarse a las rutas que se asignan al limitador de tasa. La configuración del límite son instancias de la clase Illuminate\Cache\RateLimiting\Limit
. Esta clase contiene métodos «builder» útiles para que puedas definir rápidamente tu límite. El nombre del limitador de tasa puede ser cualquier cadena que desees:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}
Si la solicitud entrante excede el límite de tasa especificado, Laravel devolverá automáticamente una respuesta con un código de estado HTTP 429. Si deseas definir tu propia respuesta que debe ser devuelta por un límite de tasa, puedes usar el método response
:
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});
Dado que los callbacks del limitador de tasa reciben la instancia de la solicitud HTTP entrante, puedes construir el límite de tasa apropiado dinámicamente basado en la solicitud entrante o el usuario autenticado:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});
Segmentando Límites de Tasa
A veces puede que desees segmentar los límites de tasa por algún valor arbitrario. Por ejemplo, puede que desees permitir a los usuarios acceder a una ruta dada 100 veces por minuto por dirección IP. Para lograr esto, puedes usar el método by
al construir tu límite de tasa:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});
Para ilustrar esta característica usando otro ejemplo, podemos limitar el acceso a la ruta a 100 veces por minuto por ID de usuario autenticado o 10 veces por minuto por dirección IP para invitados:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()
? Limit::perMinute(100)->by($request->user()->id)
: Limit::perMinute(10)->by($request->ip());
});
Múltiples Límites de Tasa
Si es necesario, puedes devolver un array de límites de tasa para una configuración de limitador de tasa dada. Cada límite de tasa será evaluado para la ruta basado en el orden en que están colocados dentro del array:
RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});
Adjuntando Limitadores de Tasa a Rutas
Los limitadores de tasa pueden ser adjuntados a rutas o grupos de rutas usando el middleware throttle
. El middleware throttle
acepta el nombre del limitador de tasa que deseas asignar a la ruta:
Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
Route::post('/video', function () {
// ...
});
});
Limitación de Tasa con Redis
Por defecto, el middleware throttle
está mapeado a la clase Illuminate\Routing\Middleware\ThrottleRequests
. Sin embargo, si estás usando Redis como el driver de caché de tu aplicación, puede que desees instruir a Laravel para que use Redis para gestionar la limitación de tasa. Para hacerlo, debes usar el método throttleWithRedis
en el archivo bootstrap/app.php
de tu aplicación. Este método mapea el middleware throttle
a la clase Illuminate\Routing\Middleware\ThrottleRequestsWithRedis
:
->withMiddleware(function (Middleware $middleware) {
$middleware->throttleWithRedis();
// ...
})
Suplantación de Método en Formularios
Los formularios HTML no soportan acciones PUT
, PATCH
o DELETE
. Por lo tanto, al definir rutas PUT
, PATCH
o DELETE
que se llaman desde un formulario HTML, necesitarás agregar un campo oculto _method
al formulario. El valor enviado con el campo _method
se usará como el método de solicitud HTTP:
<form action="/example" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
Para mayor comodidad, puedes usar la directiva @method
de Blade para generar el campo de entrada _method
:
<form action="/example" method="POST">
@method('PUT')
@csrf
</form>
Accediendo a la Ruta Actual
Puedes usar los métodos current
, currentRouteName
y currentRouteAction
en la facade Route
para acceder a información sobre la ruta que maneja la solicitud entrante:
use Illuminate\Support\Facades\Route;
$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string
Puedes consultar la documentación de la API tanto para la clase subyacente de la facade Route
como para la instancia de Route
para revisar todos los métodos que están disponibles en las clases de enrutador y ruta.
Intercambio de Recursos de Origen Cruzado (CORS)
Laravel puede responder automáticamente a solicitudes HTTP OPTIONS
de CORS con valores que configures. Las solicitudes OPTIONS
serán manejadas automáticamente por el middleware HandleCors
que se incluye automáticamente en la pila de middleware global de tu aplicación.
A veces, puede que necesites personalizar los valores de configuración de CORS para tu aplicación. Puedes hacerlo publicando el archivo de configuración de CORS usando el comando Artisan config:publish
:
php artisan config:publish cors
Este comando colocará un archivo de configuración cors.php
dentro del directorio config
de tu aplicación.
Para más información sobre CORS y los encabezados CORS, por favor consulta la documentación web de MDN sobre CORS.
Cacheo de Rutas
Al desplegar tu aplicación a producción, debes aprovechar el cacheo de rutas de Laravel. Usar el cacheo de rutas disminuirá drásticamente el tiempo que toma registrar todas las rutas de tu aplicación. Para generar un cache de rutas, ejecuta el comando Artisan route:cache
:
php artisan route:cache
Después de ejecutar este comando, tu archivo de rutas en cache se cargará en cada solicitud. Recuerda, si agregas nuevas rutas necesitarás generar un nuevo cache de rutas. Debido a esto, solo debes ejecutar el comando route:cache
durante el despliegue de tu proyecto.
Puedes usar el comando route:clear
para limpiar el cache de rutas:
php artisan route:clear