1. Conceptos básicos
  2. Enrutamiento

Únete a nuestra comunidad de Telegram @webblend!

Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.

Enrutamiento Básico

Las rutas más básicas de Laravel aceptan una URI y un cierre, proporcionando un método muy simple y expresivo para definir rutas y comportamientos sin complicados archivos de configuración de enrutamiento:

use Illuminate\Support\Facades\Route;
 
Route::get('/greeting', function () {
return 'Hello World';
});

Los Archivos de Rutas Predeterminados

Todas las rutas de Laravel se definen en tus archivos de ruta, que se encuentran en el directorio routes. Estos archivos se cargan automáticamente mediante el App\Providers\RouteServiceProvider de tu aplicación. El archivo routes/web.php define rutas para tu interfaz web. Estas rutas se asignan al grupo de middleware web, que proporciona funciones como el estado de sesión y la protección CSRF. Las rutas en routes/api.php son sin estado y se les asigna el grupo de middleware api.

Para la mayoría de las aplicaciones, comenzarás definiendo rutas en tu archivo routes/web.php. Las rutas definidas en routes/web.php se pueden acceder ingresando la URL definida de la ruta 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']);

Las rutas definidas en el archivo routes/api.php están anidadas dentro de un grupo de rutas por el RouteServiceProvider. Dentro de este grupo, el prefijo /api se aplica automáticamente, por lo que no es necesario aplicarlo manualmente a cada ruta en el archivo. Puedes modificar el prefijo y otras opciones del grupo de rutas al modificar la clase RouteServiceProvider.

Métodos de Enrutador Disponibles

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, es posible que necesites registrar una ruta que responda a varios verbos HTTP. Puedes hacerlo utilizando el método match. O incluso puedes registrar una ruta que responda a todos los verbos HTTP utilizando el método any:

Route::match(['get', 'post'], '/', function () {
// ...
});
 
Route::any('/', function () {
// ...
});

Nota Cuando defines varias rutas que comparten la misma URI, las rutas que utilizan los métodos get, post, put, patch, delete y options deben definirse antes que las rutas que utilizan los métodos any, match y redirect. Esto asegura que la solicitud entrante coincida con la ruta correcta.

Inyección de Dependencias

Puedes hacer type-hint a 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 hacer type-hint a 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 que 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 otra URI, puedes utilizar el método Route::redirect. Este método proporciona un atajo conveniente para no tener 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 utilizando el tercer parámetro opcional:

Route::redirect('/here', '/there', 301);

O puedes utilizar el método Route::permanentRedirect para devolver un código de estado 301:

Route::permanentRedirect('/here', '/there');

Advertencia Cuando uses parámetros de ruta en rutas de redirección, los siguientes parámetros están reservados por Laravel y no se pueden usar: destination y status.

Rutas de Vista

Si tu ruta solo necesita devolver una vista, puedes utilizar el método Route::view. Al igual que el método redirect, este método proporciona un atajo simple para no tener que definir una ruta completa o un controlador. El método view acepta una URI como su primer argumento y un nombre de vista como su segundo argumento. Además, puedes proporcionar una matriz de datos para pasar a la vista como tercer argumento opcional:

Route::view('/welcome', 'welcome');
 
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

Advertencia Cuando uses parámetros de ruta en rutas de vista, los siguientes parámetros están reservados por Laravel y no se pueden usar: view, data, status y headers.

La Lista de Rutas

El comando Artisan route:list puede proporcionar fácilmente una descripción general de todas las rutas definidas por tu aplicación:

php artisan route:list

Por defecto, los middleware de ruta asignados a cada ruta no se mostrarán en la salida de route:list; sin embargo, puedes indicar a Laravel que muestre los middleware de ruta y los nombres de grupos de middleware agregando la opción -v al comando:

php artisan route:list -v
 
# Expand middleware groups...
php artisan route:list -vv

También puedes indicar a Laravel que solo muestre las rutas que comienzan con una URI específica:

php artisan route:list --path=api

Además, puedes indicar a Laravel que oculte las rutas definidas por paquetes de terceros proporcionando la opción --except-vendor al ejecutar el comando route:list:

php artisan route:list --except-vendor

Del mismo modo, también puedes indicar a Laravel que solo muestre las rutas definidas por paquetes de terceros proporcionando la opción --only-vendor al ejecutar el comando route:list:

php artisan route:list --only-vendor

Parámetros de Ruta

Parámetros Obligatorios

A veces necesitarás capturar segmentos de la URI en 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 necesites para tu ruta:

Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});

Los parámetros de ruta siempre están encerrados entre llaves {} y deben consistir en caracteres alfabéticos. Los guiones bajos (_) también son aceptables en los nombres de los parámetros de ruta. Los parámetros de ruta se inyectan en las devoluciones de llamada de ruta/controlador en función de su orden; los nombres de los argumentos de la devolución de llamada del controlador no importan.

Parámetros e Inyección de Dependencias

Si tu ruta tiene dependencias que te gustaría que el contenedor de servicios de Laravel inyecte automáticamente en la devolución de llamada 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

En ocasiones, es posible que necesites especificar un parámetro de ruta que no siempre esté presente en la URI. Puedes hacerlo colocando un signo ? después del nombre del parámetro. Asegúrate de darle un valor predeterminado a la variable correspondiente de la ruta:

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 mediante 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 restringirse 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 utilizados tienen métodos auxiliares 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']);

Si la solicitud entrante no coincide con las restricciones de patrones de la ruta, se devolverá una respuesta HTTP 404.

Restricciones Globales

Si deseas que un parámetro de ruta esté siempre restringido por una expresión regular específica, puedes usar el método pattern. Debes definir estos patrones en el método boot de tu clase App\Providers\RouteServiceProvider:

/**
* Define tus vinculaciones de modelos de ruta, filtros de patrones, etc.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}

Una vez que se haya definido el patrón, se aplicará automáticamente a todas las rutas que utilicen ese nombre de parámetro:

Route::get('/user/{id}', function (string $id) {
// Solo se ejecuta si {id} es numérico...
});

Barras Inclinadas Adelante Codificadas

El componente de enrutamiento de Laravel permite que todos los caracteres excepto / estén presentes en los valores de los parámetros de ruta. Debes permitir explícitamente / como parte de tu marcador de posición usando una condición de expresión regular where:

Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');

Advertencia Solo se admiten barras inclinadas codificadas dentro del último segmento de la ruta.

Rutas con Nombre

Las rutas con nombre 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 controlador:

Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');

Advertencia Los nombres de ruta siempre deben ser únicos.

Generación de URLs a Rutas con Nombre

Una vez que hayas asignado un nombre a una ruta específica, puedes utilizar el nombre de la ruta al generar URLs o redirecciones mediante las funciones auxiliares route y redirect de Laravel:

// Generación de URL...
$url = route('profile');
 
// Generación de redirecciones...
return redirect()->route('profile');
 
return to_route('profile');

Si la ruta con nombre define parámetros, puedes pasar los parámetros como 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 la matriz, 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

Nota En ocasiones, es posible que desees especificar valores predeterminados para los parámetros de URL en toda la solicitud, como el idioma actual. Para lograr esto, puedes usar el método URL::defaults.

Inspección de la Ruta Actual

Si deseas determinar si la solicitud actual se dirigió a una ruta con nombre específico, puedes utilizar el método named en una instancia de ruta. 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, en 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 principal. 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 inclinadas en los prefijos de URI se agregan automáticamente cuando sea necesario.

Middleware

Para asignar middleware a todas las rutas dentro de un grupo, puedes utilizar el método middleware antes de definir el grupo. Los middleware se ejecutan en el orden en que se enumeran en la matriz:

Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Usa el primer y segundo middleware...
});
 
Route::get('/user/profile', function () {
// Usa el primer y segundo middleware...
});
});

Controladores

Si un grupo de rutas utiliza todos el mismo controlador, puedes utilizar 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 por Subdominios

Los grupos de rutas también se pueden utilizar para manejar el enrutamiento por subdominios. Los subdominios pueden asignarse a parámetros de ruta al igual que las URI de ruta, lo que te permite capturar una parte del subdominio para su uso en tu ruta o controlador. El subdominio se puede especificar 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) {
// ...
});
});

Advertencia Para garantizar que las rutas de subdominio sean accesibles, debes registrar las rutas de subdominio antes de registrar las rutas de dominio raíz. Esto evitará que las rutas de dominio raíz sobrescriban las rutas de subdominio que tienen la misma ruta URI.

Prefijos de Rutas

El método prefix se puede utilizar para agregar un prefijo a cada ruta en el grupo con una URI dada. Por ejemplo, es posible que desees agregar el prefijo admin a todas las URIs de ruta dentro del grupo:

Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Coincide con la URL "/admin/users"
});
});

Prefijos de Nombres de Rutas

El método name se puede utilizar para agregar un prefijo a cada nombre de ruta en el grupo con una cadena dada. Por ejemplo, es posible que desees agregar el prefijo admin a todos los nombres de las rutas en el grupo. La cadena dada se agrega al nombre de la ruta exactamente como se especifica, así que asegúrate de proporcionar el carácter . al final del prefijo:

Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Nombre de ruta asignado "admin.users"...
})->name('users');
});

Vinculación de Modelos de Ruta

Cuando inyectas un ID de modelo en una ruta o acción de controlador, a menudo consultas la base de datos para recuperar el modelo que corresponde a ese ID. La resolución implícita de modelos de ruta de Laravel proporciona una forma conveniente de inyectar automáticamente las instancias de 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.

Vinculación Implícita

Laravel resuelve automáticamente modelos Eloquent definidos en rutas o acciones de controlador cuyos nombres de variables con tipo coinciden con un nombre de 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 un tipo de dato App\Models\User y el nombre de la variable coincide con el segmento de URI {user}, Laravel inyectará automáticamente la instancia del modelo que tiene un ID coincidente con el valor correspondiente de la 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, la vinculación implícita también es posible al usar métodos de controlador. Nuevamente, ten en cuenta que el segmento de URI {user} coincide con la variable $user en el controlador que contiene una indicación de 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 Eliminados Suavemente

Normalmente, la vinculación implícita de modelos no recuperará modelos que hayan sido eliminados de forma suave. Sin embargo, puedes indicar a la vinculación implícita que recupere estos modelos encadenando el método withTrashed en la definición de tu ruta:

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
return $user->email;
})->withTrashed();

Personalización de la Clave

A veces, es posible que desees resolver modelos Eloquent utilizando una columna que no sea 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 la vinculación de modelos use siempre una columna de base de datos distinta de id al recuperar una clase de modelo dada, puedes anular 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 Ámbitos

Cuando vinculas implícitamente varios modelos Eloquent en una sola definición de ruta, es posible que desees delimitar el segundo modelo Eloquent de modo que sea un hijo del modelo Eloquent anterior. Por ejemplo, considera esta definición de ruta que recupera una publicación de blog por su 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;
});

Cuando usas una vinculación implícita de clave personalizada como parámetro de ruta anidado, Laravel automáticamente delimitará la consulta para recuperar el modelo anidado por su padre utilizando 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 en plural del nombre del parámetro de ruta) que se puede utilizar para recuperar el modelo Post.

Si lo deseas, puedes indicar a Laravel que delimite las vinculaciones "hijas" 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 indicar a un grupo completo de definiciones de ruta que use vinculaciones delimitadas:

Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});

De manera similar, puedes indicar explícitamente a Laravel que no delimite las vinculaciones invocando el método withoutScopedBindings:

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();

Personalización del Comportamiento de Modelo Faltante

Normalmente, se generará una respuesta HTTP 404 si no se encuentra un modelo vinculado implícitamente. Sin embargo, puedes personalizar este comportamiento llamando al método missing al definir tu ruta. El método missing acepta un cierre que se invocará si no se puede encontrar un modelo vinculado 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');
});

Vinculación Implícita de Enumeraciones

PHP 8.1 introdujo el soporte para Enums. Para complementar esta característica, Laravel te permite indicar como tipo de dato un Enum respaldado por cadena en la definición de tu ruta y Laravel solo invocará la ruta si ese segmento de ruta corresponde a un valor Enum válido. De lo contrario, se devolverá automáticamente una respuesta HTTP 404. Por ejemplo, dada la 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 automáticamente:

use App\Enums\Category;
use Illuminate\Support\Facades\Route;
 
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});

Vinculación Explícita

No es necesario utilizar la resolución implícita de modelos basada en convenciones de Laravel para utilizar la vinculación de modelos. También puedes definir explícitamente cómo los parámetros de ruta se corresponden con los modelos. Para registrar una vinculación explícita, utiliza el método model del enrutador para especificar la clase para un parámetro dado. Debes definir tus vinculaciones de modelos explícitas al principio del método boot de la clase RouteServiceProvider de tu aplicación:

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Define tus vinculaciones de modelos de ruta, filtros de patrones, etc.
*/
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 vinculado todos los parámetros {user} al modelo App\Models\User, se inyectará una instancia de esa clase en la ruta. Así que, por ejemplo, una solicitud a users/1 inyectará la instancia 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.

Personalización de la Lógica de Resolución

Si deseas definir tu propia lógica de resolución de vinculación de modelos, puedes utilizar el método Route::bind. El cierre que pases al método bind recibirá el valor del segmento de URI y deberá devolver la instancia de la clase que se debe inyectar en la ruta. Nuevamente, esta personalización debe realizarse en el método boot de tu RouteServiceProvider de la aplicación:

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Define tus vinculaciones de modelos de ruta, filtros de patrones, etc.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
 
// ...
}

Alternativamente, puedes anular el método resolveRouteBinding en tu modelo Eloquent. Este método recibirá el valor del segmento de URI y deberá devolver la instancia de la clase que se debe inyectar en la ruta:

/**
* Recupera el modelo para un valor vinculado.
*
* @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 delimitación de vinculación implícita, se utilizará el método resolveChildRouteBinding para resolver la vinculación secundaria del modelo padre:

/**
* Recupera el modelo secundario para un valor vinculado.
*
* @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 Respaldo

Utilizando 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 gestionadas automáticamente renderizarán una página "404" a través del manejador de excepciones de tu aplicación. Sin embargo, dado que normalmente definirías la ruta fallback dentro de tu archivo routes/web.php, todos los middleware en el grupo de middleware web se aplicarán a la ruta. Eres libre de agregar middleware adicional a esta ruta según sea necesario:

Route::fallback(function () {
// ...
});

Advertencia La ruta de respaldo siempre debe ser la última ruta registrada por tu aplicación.

Control de Velocidad

Definición de Limitadores de Velocidad

Laravel incluye servicios de límite de velocidad potentes y personalizables que puedes utilizar para restringir la cantidad de tráfico para una ruta dada o un grupo de rutas. Para empezar, debes definir configuraciones de límite de velocidad que se ajusten a las necesidades de tu aplicación.

Típicamente, los limitadores de velocidad se definen dentro del método boot de la clase App\Providers\RouteServiceProvider de tu aplicación. De hecho, esta clase ya incluye una definición de limitador de velocidad que se aplica a las rutas en el archivo routes/api.php de tu aplicación:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Define tus vinculaciones de modelos de ruta, filtros de patrones y otra configuración de ruta.
*/
protected function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
 
// ...
}

Los limitadores de velocidad se definen utilizando el método for de la fachada RateLimiter. El método for acepta un nombre de limitador de velocidad y un cierre que devuelve la configuración de límite que debe aplicarse a las rutas que se asignan al limitador de velocidad. La configuración del límite es una instancia de la clase Illuminate\Cache\RateLimiting\Limit. Esta clase contiene útiles métodos "builder" para que puedas definir rápidamente tu límite. El nombre del limitador de velocidad puede ser cualquier cadena que desees:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Define tus vinculaciones de modelos de ruta, filtros de patrones y otra configuración de ruta.
*/
protected function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
 
// ...
}

Si la solicitud entrante excede el límite de velocidad especificado, Laravel devolverá automáticamente una respuesta con un código de estado 429. Si deseas definir tu propia respuesta que se debe devolver por un límite de velocidad, 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 velocidad reciben la instancia de la solicitud HTTP entrante, puedes construir el límite de velocidad adecuado dinámicamente según la solicitud entrante o el usuario autenticado:

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});

Segmentación de Limitaciones de Velocidad

A veces, es posible que desees segmentar los límites de velocidad por algún valor arbitrario. Por ejemplo, es posible que desees permitir que los usuarios accedan a una ruta determinada 100 veces por minuto por dirección IP. Para lograr esto, puedes utilizar el método by al construir tu límite de velocidad:

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});

Para ilustrar esta característica utilizando 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 los 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 Limitaciones de Velocidad

Si es necesario, puedes devolver un array de límites de velocidad para una configuración dada de limitador de velocidad. Cada límite de velocidad se evaluará para la ruta según el orden en que se colocan dentro del array:

RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});

Asociar Limitadores de Velocidad a Rutas

Los limitadores de velocidad se pueden adjuntar a rutas o grupos de rutas utilizando el middleware throttle. El middleware throttle acepta el nombre del limitador de velocidad que deseas asignar a la ruta:

Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
 
Route::post('/video', function () {
// ...
});
});

Limitación de Velocidad con Redis

Típicamente, el middleware throttle se asigna a la clase Illuminate\Routing\Middleware\ThrottleRequests. Este mapeo está definido en el kernel HTTP de tu aplicación (App\Http\Kernel). Sin embargo, si estás utilizando Redis como el controlador de caché de tu aplicación, es posible que desees cambiar este mapeo para usar la clase Illuminate\Routing\Middleware\ThrottleRequestsWithRedis. Esta clase es más eficiente para gestionar la limitación de velocidad utilizando Redis:

'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,

Simulación de Métodos de Formulario

Los formularios HTML no admiten acciones PUT, PATCH o DELETE. Entonces, al definir rutas PUT, PATCH o DELETE que se llaman desde un formulario HTML, deberás agregar un campo oculto _method al formulario. El valor enviado con el campo _method se utilizará 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>

Acceso a la Ruta Actual

Puedes utilizar los métodos current, currentRouteName y currentRouteAction en la fachada 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 fachada Route como para la instancia de Route para revisar todos los métodos disponibles en las clases de enrutador y ruta.

Intercambio de Recursos entre Dominios (CORS)

Laravel puede responder automáticamente a las solicitudes HTTP OPTIONS de CORS con valores que configures. Todas las configuraciones de CORS se pueden configurar en el archivo de configuración config/cors.php de tu aplicación. Las solicitudes OPTIONS serán manejadas automáticamente por el middleware HandleCors que se incluye de forma predeterminada en tu pila de middleware global. Tu pila de middleware global se encuentra en el kernel HTTP de tu aplicación (App\Http\Kernel).

Nota Para obtener más información sobre CORS y las cabeceras CORS, consulta la documentación web de MDN sobre CORS.

Caché de Rutas

Cuando despliegues tu aplicación en producción, deberías aprovechar la caché de rutas de Laravel. El uso de la caché de rutas disminuirá drásticamente el tiempo necesario para registrar todas las rutas de tu aplicación. Para generar una caché de rutas, ejecuta el comando Artisan route:cache:

php artisan route:cache

Después de ejecutar este comando, tu archivo de rutas en caché se cargará en cada solicitud. Recuerda, si agregas nuevas rutas, deberás generar una nueva caché 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 borrar la caché de rutas:

php artisan route:clear