Rutas

# Enrutamiento básico

La ruta más básica en Laravel únicamente acepta la URI y un Closure, ofreciendo una forma muy sencilla y expresiva de definir rutas:

Route::get('foo', function () {
    return 'Hello World';
});

Los archivos de la ruta por defecto

Todas las rutas de Laravel se definen en los archivos que se encuentran en la carpeta routes. El framework carga estos archivos de forma automática. El archivo routes/web.php define las rutas para la interfaz web. A estas rutas se les asigna el grupo de middleware web, el cual proporciona algunas características como el estado de la sesión y la protección CSRF. Las rutas en routes/api.php no tienen estado y se les asigna el grupo de middleware api.

Para la mayoría de aplicaciones, se comenzará definiendo las rutas en el archivo routes/web.php. Se puede acceder a las rutas definidas en routes/web.php simplemente escribiendo la URI definida en el navegador. Por ejemplo, se puede acceder a la siguiente ruta simplemente accediendo a http://tu-app.dev/user desde el navegador:

use App\Http\Controllers\UserController;

Route::get('/user', [UserController::class, 'index']);

El RouteServiceProvider anidará las rutas definidas en routes/api.php bajo un grupo de rutas. Este grupo añadirá el URI /api como prefijo de forma automática, por lo que no es necesario definirlo en cada una de las rutas del archivo. Se puede modificar el prefijo y otras opciones del grupo modificando la clase RouteServiceProvider.

Métodos de enrutamiento disponibles

El router permite registrar rutas que respondan 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);

En ocasiones puede ser necesario una ruta que responda a varios verbos HTTP. Puede hacerse utilizando el método match. O incluso se puede registrar una ruta que responda a todos los verbos HTTP utilizando el método any:

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

Route::any('/', function () {
    //
});

Protección CSRF

Cualquier formulario HTML que apunte a una ruta POSTPUT o DELETE definida en el archivo de rutas web debe incluir un campo con un token CSRF. De lo contrario, la petición se rechazará. Se puede averiguar más sobre protección CSRF en la documentación CSRF:

<form method="POST" action="/profile">
    @csrf
    ...
</form>

Redireccionar las rutas

Si está definiendo una ruta que redirige a otra URI, puede 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. Puede personalizar el código de estado utilizando el tercer parámetro opcional:

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

Puede usar el método Route::permanentRedirect ara devolver un código de estado 301:

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

Rutas con vistas

Si únicamente se necesita devolver una vista desde una ruta, se puede utilizar el método Route::view. Al igual que el método redirect, este método es como un acceso directo para no tener que definir la ruta completa o un controlador. El método view acepta una URI como primer parámetro y un nombre de vista como segundo. Además, se le puede pasar un array de datos a la vista como tercer parámetro opcional:

Route::view('/welcome', 'welcome');

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

# Rutas con parámetros

Parámetros requeridos

A veces necesitarás capturar segmentos de la URI dentro de tu ruta. Por ejemplo, puede que necesites capturar el ID de un usuario de la URL. Puede hacerlo definiendo los parámetros de la ruta:

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

Puede definir tantos parámetros de ruta como sean requeridos por su ruta:

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

Los parámetros de ruta se definen siempre dentro de llaves {} y deben contener únicamente caracteres alfabéticos y nunca contener - (guiones). Instead of using the - character, use an underscore (_). Los parámetros de rutas se inyectan directamente en los callback/controladores en orden – los nombres de los argumentos no afectan.

Parámetros opcionales

A veces es necesario especificar un parámetro, pero la presencia de este parámetro es opcional. Se puede definir simplemente añadiendo el símbolo ? detrás del nombre del parámetro. Asegúrese de dar a esa variable un valor por defecto en su callback/controlador:

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

Expresiones regulares

Es posible limitar el formato de los elementos dentro de los parámetros de una ruta usando el método where en una instancia de Route. El método where acepta el nombre del parámetro y la expresión regular que define como se debe limitar el parámetro:

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Restricciones globales

Si se desea que un parámetro de ruta siempre este limitado por una expresión regular definida, se puede hace utilizando el método pattern. Estos patrones se deben definir en el método boot dentro del RouteServiceProvider:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');
}

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

Route::get('user/{id}', function ($id) {
    // Only executed if {id} is numeric...
});

Cifrado de los cortes hacia adelante

El componente de enrutamiento de Laravel permite todos los caracteres excepto /. Debe permitir explícitamente que / sea parte de su marcador de posición usando una expresión regular de la condición where:

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

Las barras codificadas de avance sólo se admiten en el último segmento de ruta.

# Nombre de rutas

Las rutas con nombre permiten la generación de URL o redirecciones para rutas específicas. Se puede especificar el nombre de una ruta encadenando el método name a la definición de la ruta:

Route::get('user/profile', function () {
    //
})->name('profile');

También se pueden especificar nombres de rutas para acciones de controladores:

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

Los nombres de las rutas siempre deben ser únicos.

Generando URLs para las rutas nombradas

Once you have assigned a name to a given route, you may use the route's name when generating URLs or redirects via the global route function:

// Generating URLs...
$url = route('profile');

// Generating Redirects...
return redirect()->route('profile');

Si la ruta nombrada define parámetros, puede pasar los parámetros como segundo argumento a la función "route". Los parámetros dados se insertarán automáticamente en la URL en sus posiciones correctas:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

Si pasas parámetros adicionales en el array, esos pares clave/valor se añadirán automáticamente a la cadena de consulta de la URL generada

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1, 'photos' => 'yes']);

// /user/1/profile?photos=yes

A veces, puede que desee especificar valores predeterminados de solicitud para los parámetros de la URL, como la localidad actual. Para ello, puede utilizar la función URL::defaults method.

Inspeccionando la ruta actual

Para determinar si la petición actual coincide con el nombre de alguna ruta, se puede utilizar el método named de una instancia de Route. Por ejemplo, se puede comprobar el nombre de la ruta actual desde un middleware de ruta:

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

# Grupo de rutas

Los Grupos de Rutas permiten compartir atributos de ruta, por ejemplo middleware o namespaces, a un grupo de rutas sin necesidad de definir los atributos a cada una de manera individual. Los atributos compartidos se pasan en un como array al primer parámetro del método Route::group.

Los grupos anidados intentan "merge"inteligentemente los atributos con su grupo matriz. Las condiciones Middleware y where se fusionan mientras que los nombres y prefijos se añaden. Los delimitadores del espacio de nombres y las barras en los prefijos URI se añaden automáticamente cuando es apropiado.

Middleware

Para asignar un middleware a todas las rutas de un grupo, se puede utilizar el método middleware antes de definir el grupo. Los middleware se ejecutarán en en el mismo orden que se pasen en el array:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second middleware...
    });

    Route::get('user/profile', function () {
        // Uses first & second middleware...
    });
});

Enrutamiento de sub-dominio

Los grupos de rutas también pueden utilizarse para manejar las rutas de los subdominios. A los subdominios se les pueden asignar parámetros de ruta, al igual que a las URI de las rutas, lo que le permite capturar una parte del subdominio para utilizarla en su ruta o controlador. El subdominio puede especificarse llamando al método domain antes de definir el grupo:

Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

Para asegurarse de que las rutas de sus subdominios sean accesibles, debería registrar las rutas de los subdominios antes de registrar las rutas del 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 ruta

El método prefix se puede utilizar para prefijar cada ruta en un grupo con una URI concreta. Por ejemplo, para añadir un prefijo a todas las URIs en el grupo admin:

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

Prefijos del nombre de ruta

El método name puede utilizarse para anteponer a cada nombre de ruta del grupo una cadena determinada. Por ejemplo, es posible que desee anteponer a todos los nombres de ruta agrupados el prefijo "admin". La cadena dada es prefijada al nombre de la ruta exactamente como se especifica, por lo que nos aseguraremos de proporcionar el carácter de seguimiento . en el prefijo:

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

# Route Model Binding

Cuando se inyecta una identificación de modelo a una ruta o acción del controlador, a menudo se consulta para recuperar el modelo que corresponde a esa identificación. La vinculación del modelo de ruta de Laravel proporciona una forma conveniente de inyectar automáticamente las instancias del modelo directamente en sus rutas. Por ejemplo, en lugar de inyectar el ID de un usuario, puede inyectar toda la instancia de modelo "User" que corresponde al ID dado.

Implicit Binding

Laravel resuelve automáticamente los modelos elocuentes definidos en las rutas o acciones de los controladores cuyos nombres de las variables con insinuación de tipo coinciden con el nombre de un segmento de ruta. Por ejemplo:

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

Dado que la variable $user está escrita a máquina como el modelo Eloquent App\Models\User y el nombre de la variable coincide con el {user} Segmento de URI, Laravel inyectará automáticamente la instancia de modelo que tenga un ID que coincida con el valor correspondiente de la solicitud de URI. Si no se encuentra una instancia de modelo coincidente en la base de datos, se generará automáticamente una respuesta HTTP 404.

Personalizar la clave

A veces puede desear resolver los modelos elocuentes usando una columna diferente a la de identificación. Para ello, puede especificar la columna en la definición de los parámetros de la ruta:

Route::get('api/posts/{post:slug}', function (App\Models\Post $post) {
    return $post;
});

Llaves personalizadas y alcance

A veces, cuando se vinculan implícitamente varios modelos elocuentes en una sola definición de ruta, puede que se desee ampliar el alcance del segundo modelo elocuente de manera que sea un hijo del primer modelo elocuente. Por ejemplo, considere esta situación que recupera una entrada de blog por babosa para un usuario específico:

use App\Models\Post;
use App\Models\User;

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

Cuando se utiliza un enlace implícito con clave personalizada como parámetro de ruta anidada, Laravel automáticamente ampliará la consulta para recuperar el modelo anidado por su progenitor utilizando convenciones para adivinar el nombre de la relación en el progenitor. En este caso, se asumirá que el modelo User tiene una relación denominada posts (el plural del nombre del parámetro de ruta) que puede utilizarse para recuperar el modelo Post.

Personalización del nombre de la clave por defecto

Si desea que la vinculación del modelo utilice una columna de la base de datos por defecto que no sea id al recuperar una clase de modelo determinada, puede anular el método getRouteKeyName en el modelo elocuente:

/**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

Explicit Binding

Para registrar una vinculación explícita, utilice el método model del enrutador para especificar la clase de un parámetro determinado. Debe definir sus vinculaciones explícitas de modelo al principio del método boot de su clase RouteServiceProvider:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::model('user', App\Models\User::class);

    // ...
}

A continuación, defina una ruta que contenga un parámetro {user}:

Route::get('profile/{user}', function (App\Models\User $user) {
    //
});

Dado que hemos vinculado todos los parámetros de {user} al modelo App\Models\User se inyectará una instancia de User" en la ruta. Así, por ejemplo, una solicitud de profile/1 inyectará la instancia User de la base de datos que tiene un ID 1.

Si no se encuentra una instancia de modelo coincidente en la base de datos, se generará automáticamente una respuesta HTTP 404.

Personalizar la lógica de la resolución

Si desea utilizar su propia lógica de resolución, puede utilizar el método Route::bind. El Closure que se pasa al método bind recibirá el valor del segmento de URI y deberá devolver la instancia de la clase que debe ser inyectada en la ruta:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::bind('user', function ($value) {
        return App\Models\User::where('name', $value)->firstOrFail();
    });

    // ...
}

Alternativamente, puede anular el método resolveRouteBinding en su modelo Elocuente. Este método recibirá el valor del segmento de URI y debería devolver la instancia de la clase que debe ser inyectada en la ruta:

/**
 * Retrieve the model for a bound value.
 *
 * @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();
}

# Fallback Routes

Usando el método Route::fallback, puede definir una ruta que se ejecutará cuando ninguna otra ruta coincida con la solicitud entrante. Típicamente, las solicitudes no manejadas automáticamente mostrarán una página "404" a través del manejador de excepciones de su aplicación. Sin embargo, como puede definir la ruta "fallback" dentro de su archivo "routes/web.php", todo el middleware del grupo de middleware web se aplicará a la ruta. Eres libre de añadir middleware adicional a esta ruta según sea necesario:

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

La ruta alternativa siempre debe ser la última ruta registrada en su solicitud.

# Rate Limiting

Definiendo Rate Limiters

Laravel incluye potentes y personalizables servicios de limitación de tarifas que puede utilizar para restringir la cantidad de tráfico para una determinada ruta o grupo de rutas. Para empezar, debe definir configuraciones de limitador de tarifa que se ajusten a las necesidades de su aplicación. Típicamente, esto se puede hacer en el RouteServiceProvider.

Los limitadores de tasa se definen utilizando el método for de la fachada RateLimiter. El método for acepta un nombre de limitador de tarifa y un cierre que devuelve la configuración de límite que debería aplicarse a las rutas a las que se asigna este limitador de tarifa:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

Si la solicitud entrante excede el límite de la tasa especificada, una respuesta con un código de estado HTTP 429 será devuelta automáticamente por Laravel. Si desea definir su propia respuesta que debe ser devuelta por un límite de tasa, puede utilizar el método response:

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000)->response(function () {
        return response('Custom response...', 429);
    });
});

Dado que las devoluciones de llamadas del limitador de tasas reciben la instancia de solicitud HTTP entrante, puede 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);
});

Límites de la tasa de segmentación

A veces puede desear segmentar los límites de la tasa por algún valor arbitrario. Por ejemplo, tal vez desee permitir que los usuarios accedan a una ruta determinada 100 veces por minuto por dirección IP. Para lograr esto, puede utilizar el método by cuando construya su límite de velocidad:

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

Límites de tasas múltiples

Si es necesario, puede devolver un conjunto de límites de tasa para una configuración de limitador de tasa determinada. Cada límite de tasa será evaluado para la ruta en base al orden en que se colocan dentro del arreglo:

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

Fijación de limitadores de tasa a las rutas

Los limitadores de velocidad pueden ser adjuntados a las rutas o grupos de rutas usando el throttle middleware. El middleware del acelerador acepta el nombre del limitador de velocidad que desea asignar a la ruta:

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

    Route::post('/video', function () {
        //
    });
});

# Método de forma Spoofing

Los formularios HTML no admiten acciones de PUT, PATCH or DELETE. Así que, al definir las rutas PUT, PATCH o DELETE que son llamadas desde un formulario HTML, necesitarás añadir un campo _method oculto al formulario. El valor enviado con el campo _method será usado como el método de solicitud HTTP:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

Puedes usar la directiva Blade @method para generar el input _method:

<form action="/foo/bar" method="POST">
    @method('PUT')
    @csrf
</form>

# Acceder a la ruta actual

Puede utilizar los métodos current, currentRouteName, y currentRouteAction de la fachada Route para acceder a la información sobre la ruta que gestiona la solicitud entrante:

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

Consulte la documentación de la API tanto para la Clase subyacente de la fachada de la ruta como para La intancia de la ruta para revisar todos los métodos accesibles.

# Intercambio de Recursos de Origen Cruzado (CORS)

Laravel puede responder automáticamente a las peticiones de las OPCIONES DE CORS con los valores que usted configure. Todos los ajustes CORS pueden ser configurados en su archivo de configuración "cors" y las peticiones de OPCIONES serán manejadas automáticamente por el middleware "HandleCors" que está incluido por defecto en su pila global de middleware.

Para más información sobre el CORS y los encabezados del CORS, por favor consulte la Documentacion de la web MDN web documentation on CORS.