Rutas básicas

Las rutas de Laravel más básicas aceptan una URI y una Closure, proporcionando un método muy fácil y expresivo de definición de rutas:

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

Los archivos de ruta predeterminados

Todas las rutas de Laravel están definidas en tus archivos de ruta, los cuales están localizados en el directorio routes. Estos archivos son cargados automáticamente por el framework. El archivo routes/web.php define rutas que son para tu interfaz web. Estas rutas son asignadas al grupo de middleware web, el cual proporciona características como estado de sesión y protección CSRF. Las rutas en routes/api.php son independientes de estado y son asignadas al grupo de middleware api.

Para las principales aplicaciones, empezarás definiendo rutas en tu archivo routes/web.php. Las rutas definidas en routes/web.php pueden ser accedidas colocando la URL de la ruta definida en tu navegador. Por ejemplo, puede acceder a la siguiente ruta al navegar a http://your-app.test/user en tu navegador:

Route::get('/user', 'UserController@index');

Las rutas definidas en el archivo routes/api.php son agrupadas dentro de un grupo de ruta por el RouteServiceProvider. Dentro de este grupo, el prefijo de URI /api es aplicado automáticamente de modo que no es necesario aplicarlo manualmente en todas las rutas en el archivo. Puedes modificar el prefijo y otras opciones de grupos de ruta al modificar tu clase RouteServiceProvider.

Métodos disponibles del enrutador

El enrutador permite que registres 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);

Algunas veces puede que necesites registrar una ruta que responda a verbos HTTP múltiples. Puedes hacerlo usando el método match. También, puedes incluso registrar una ruta que responda a todos los verbos HTTP usando el método any:

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

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

Protección CSRF

Cualquiera de los formularios HTML que apunten a rutas POST, PUT, o DELETE que sean definidas en el archivo de rutas web deberían incluir un campo de token CSRF. De otra manera, la solicitud será rechazada. Puedes leer más sobre protección CSRF en la documentación de CSRF:

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

Redireccionar rutas

Si estás definiendo una ruta que redirecciona a otra URI, puedes usar el método Route::redirect. Este método proporciona una forma abreviada conveniente de modo que no tengas que definir una ruta completa o de controlador para ejecutar una redirección básica:

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

Por defecto, Route::redirect retorna un código de estado 302. Puedes personalizar el código de estado usando el tercer parámetro opcional:

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

Puedes usar el método Route::permanentRedirect para retornar un código de estado 301:

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

Rutas de vista

Si tu ruta necesita solamente devolver una vista, puedes usar el método Route::view. Igual que el método redirect, este método proporciona una forma abreviada básica de modo que no tengas que definir una ruta completa o de 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 arreglo de datos para pasar a la vista como un tercer argumento opcional:

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

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

Parámetros de ruta

Parámetros requeridos

Con frecuencia necesitarás capturar segmentos de la URI dentro de tu ruta. Por ejemplo, puedes necesitar capturar un ID de usuario de la URL. Puedes hacer eso al definir los parámetros de ruta:

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

Puedes definir tantos parámetros de ruta como requieras para tu ruta:

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

Los parámetros de ruta siempre son encerrados dentro de llaves {}, deberían consistir de caracteres alfabéticos y no pueden contener un carácter -. En lugar de usar el carácter -, usa el guión bajo (_). Los parámetros de ruta son inyectados dentro de las funciones de retorno de ruta / controlador en base a su orden – los nombres de los argumentos de la función de retorno / controlador no importan.

Parámetros opcionales

Ocasionalmente puede que necesites especificar un parámetro de ruta, pero que aparezca como un parámetro opcional de esa ruta. Puedes hacer eso al colocar un signo de interrogación ? después del nombre del parámetro. Asegúrate de dar un valor por defecto a la variable correspondiente de la ruta.

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

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

Restricciones con 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 defina cómo el parámetro debería estar conformado:

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 prefieres que un parámetro de ruta siempre esté restringido por una expresión regular dada, puedes usar el método pattern. Deberías definir estos patrones en el método boot de tu RouteServiceProvider:

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

    parent::boot();
}

Una vez que el patrón ha sido definido, es aplicado automáticamente a todas las rutas que usen ese nombre de parámetro:

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

Slashes codificados

El componente de rutas de Laravel permite todos los caracteres excepto /. Debes explícitamente permitir que / sea parte de tu placeholder usando una expresión regular de la condición where:

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

Los slashes codificados sólo están soportados dentro del último segmento de la ruta.

Rutas nombradas

Las rutas nombradas permiten la generación de URLs o redirecciones para rutas específicas de una forma conveniente. Puedes especificar un nombre para una ruta al encadenar el método name en la definición de la ruta:

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

También puedes especificar los nombres de ruta para acciones de controlador:

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

Generación de URLs para las rutas nombradas

Una vez que has asignado un nombre a una ruta dada, puedes usar el nombre de la ruta cuando estás generando URLs o redireccionas por medio de la función global route:

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

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

Si la ruta nombrada posee parámetros, puedes pasar los parámetros como el segundo argumento de la función route. Los parámetros dados serán insertados automáticamente dentro de 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 arreglo, estos pares clave / valor serán automáticamente agregados a la cadena de consulta generada de la URL:

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

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

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

Algunas veces, puedes necesitar especificar los valores predeterminados para toda la solicitud en los parámetros de URL, tal como la localización del usuario actual. Para cumplir con esto, puedes usar el método URL::defaults.

Inspeccionando la ruta actual

Si requieres determinar si la solicitud actual fue enrutada por una ruta nombrada dada, puedes usar el método named en una instancia de ruta. Por ejemplo, puedes verificar el nombre de ruta actual desde el middleware de una 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);
}

Los grupos de ruta

Los grupos de ruta permiten que tu compartas atributos de ruta, tales como los middleware o los espacios de nombres, a través de un número grande de rutas sin necesidad de definir esos atributos en cada ruta individual. Los atributos compartidos son especificados en un formato de arreglo como el primer parámetro al método Route::group.

Los grupos anidados intentan «fusionar» de forma inteligente los atributos al grupo de sus padres. Los middleware y condiciones where son mezcladas (merged) mientras que los nombres, espacios de nombres y prefijos son agregados (appended). Los delimitadores de espacio de nombre y los slashes en los prefijos de URLs son automáticamente agregados cuando es apropiado.

Los middleware

Para asignar los middleware a todas las rutas dentro de un grupo, puedes usar el método middleware antes de la definición del grupo. Los middleware son ejecutados en base al orden en el cual son listados en el arreglo:

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

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

Los espacios de nombres

Otro uso común para los grupos de ruta es la asignación del mismo espacio de nombre de PHP a un grupo de controladores usando el método namespace:

Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});

Recuerda que por defecto, el RouteServiceProvider incluye tus archivos de ruta dentro de un grupo de espacio de nombre, permitiéndote que registres rutas de controlador sin especificar el prefijo de espacio de nombre App\Http\Controllers completo. Así, puedes necesitar especificar solamente la porción del espacio de nombre que viene después del espacio de nombre App\Http\Controllers base.

El enrutamiento de subdominio

Los grupos de ruta también pueden ser usados para manejar enrutamiento de subdominio. Los subdominios pueden ser asignados a parámetros de ruta justamente como URIs de ruta, permitiéndote que captures una porción del sub-dominio para uso en tu ruta o controlador. El subdominio puede ser especificado al ejecutar el método domain antes de definir el grupo.

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

Para asegurarte de que tus rutas de subdominios sean accesibles, debes registrar rutas de subdominios antes de registrar rutas de dominio principal. Esto evitará que las rutas principales sobrescriban rutas de subdominios que tienen la misma URI.

Prefijos de rutas

El método prefix puede ser usado para poner un prefijo a cada ruta en el grupo con una URI dada. Por ejemplo, puedes desear poner un prefijo a todas las URIs de ruta dentro del grupo con admin:

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

Los prefijos de nombre de ruta

El método name puede ser usado para poner prefijo a cada nombre de ruta en el grupo con una cadena dada. Por ejemplo, puedes desear poner prefijo a todos los nombres de ruta agrupados con admin. La cadena dada es prefijada al nombre de ruta exactamente como es especificada, así que nos aseguraremos de proporcionar el carácter de terminación . en el prefijo:

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

Enlazamiento de modelo de ruta (route model binding)

Cuando estamos inyectando un ID de modelo a una ruta o acción de controlador, usualmente consultarás para obtener el modelo que corresponde a esa ID. El enlazamiento de modelo de ruta de Laravel proporciona una forma conveniente de inyectar directamente las instancias del modelo en tus rutas. Por ejemplo, en lugar de inyectar un ID de usuario, puedes inyectar la instancia del modelo User completa que coincida con el ID dado.

Enlazamiento implícito

Laravel resuelve automáticamente los modelos de Eloquent en rutas o acciones de controlador cuyos nombres de variables declaradas coincidan con un nombre de segmento de ruta. Por ejemplo:

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

Debido a que la variable $user está declarada como el modelo de Eloquent App\User y el nombre de variable coincide con el segmento de URI {user}, Laravel inyectará automáticamente la instancia del modelo que tenga un ID coincidiendo con el valor correspondiente en la URI de la solicitud. Si una instancia del modelo que coincida no es encontrada en la base de datos, una respuesta HTTP 404 será generada automáticamente.

Personalizando el nombre de clave

Si prefieres que el enlazamiento del modelo use una columna de base de datos distinta del id cuando estás obteniendo una clase de modelo dada, puedes sobreescribir el método getRouteKeyName en el modelo de Eloquent:

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

Enlazamiento explícito

Para registrar un enlazamiento explícito, usa el método model del enrutador para especificar la clase para un parámetro dado. Deberías definir tu enlazamiento del modelo explícito en el método boot de la clase RouteServiceProvider:

public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}

Seguido, define una ruta que contenga un parámetro {user}:

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

Debido a que hemos enlazado todos los parámetros de {user} al modelo App\User, una instancia User será inyectada dentro de la ruta. Así, por ejemplo, una solicitud a profile/1 inyectará la instancia de la base de datos la cual tiene una ID de 1.

Si una instancia de modelo que coincida no es encontrada en la base de datos, una respuesta HTTP 404 será generada automáticamente.

Personalizando la lógica de resolución

Si deseas usar tu propia lógica de resolución, puedes usar el método Route::bind. La Closure que pases al método bind recibirá el valor del segmento de URI y debería devolver la instancia de la clase que debería ser inyectada dentro de la ruta:

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->firstOrFail();
    });
}

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

/**
* Retrieve the model for a bound value.
*
* @param  mixed  $value
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value)
{
    return $this->where('name', $value)->firstOrFail();
}

Rutas fallback

Usando el método Route::fallback, puedes definir una ruta que será ejecutada cuando ninguna otra ruta coincida con la petición entrante. Típicamente, las peticiones no gestionadas automáticamente mostrarán una página 404 a través del manejador de excepciones de tu aplicación. Sin embargo, ya que puedes definir la ruta fallback dentro de tu archivo routes/web.php, todo middleware en el grupo web aplicará a la ruta. Eres libre de añadir middleware adicionales a esta ruta de ser necesario:

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

La ruta fallback siempre debe ser la última ruta registrada por tu aplicación.

Límite de rango

Laravel incluye un middleware para limitar el rango de acceso a rutas dentro de tu aplicación. Para empezar, asigna el middleware throttle a una ruta o grupo de rutas. EL middleware throttle acepta dos parámetros que determinan el máximo número de peticiones que pueden hacerse en un número de minutos dado. Por ejemplo, especifiquemos que un usuario autenticado puede acceder al siguiente grupo de rutas sesenta veces por minuto:

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Límite de rango dinámico

Puedes especificar un máximo de peticiones dinámicas basado en un atributo del modelo User autenticado. Por ejemplo, si tu modelo User contiene un atributo rate_limit, puedes pasar el nombre del atributo al middleware throttle de modo que sea usado para calcular el conteo máximo de peticiones:

Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Límites de rango distintos para usuarios autenticados y no autenticados

Puedes especificar diferentes límites de rango para usuarios autenticados y no autenticados. Por ejemplo, puedes especificar un máximo de 10 peticiones por minuto para usuarios no autenticados y 60 para usuarios autenticados:

Route::middleware('throttle:10|60,1')->group(function () {
    //
});

También puedes combinar esta funcionalidad con límites de rango dinámicos. Por ejemplo, si tu modelo User contiene un atributo rate_limit, puedes pasar el nombre del atributo al middleware throttle para que sea usado para calcular el número máximo de peticiones para usuarios autenticados:

Route::middleware('auth:api', 'throttle:10|rate_limit,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Segmentos de límite de rango

Típicamente, será probable que especifiques un límite de rango para toda tu API. Sin embargo, tu aplicación puede requerir diferentes límites de rango para diferentes segmentos de tu API. Si este es el caso, necesitarás pasar un nombre de segmento como tercer argumento del middleware throttle:

Route::middleware('auth:api')->group(function () {
    Route::middleware('throttle:60,1,default')->group(function () {
        Route::get('/servers', function () {
            //
        });
    });

    Route::middleware('throttle:60,1,deletes')->group(function () {
        Route::delete('/servers/{id}', function () {
            //
        });
    });
});

La suplantación de método del formulario

Los formularios HTML no soportan acciones PUT, PATCH o DELETE. Así que, cuando estés definiendo rutas PUT, PATCH o DELETE que son llamadas desde un formulario HTML, necesitarás agregar un campo _method oculto para el 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 campo _method:

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

Accediendo la ruta actual

Puedes usar los métodos current, currentRouteName, y currentRouteAction en la clase facade Route para acceder a la información sobre el manejador de ruta de la solicitud entrante:

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

Consulta la documentación de la API sobre la clase subyacente de la clase facade Route y la instancia de ruta para revisar todos los métodos disponibles.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Contratos - Documentación de Laravel 6 Lección siguiente Middleware - Documentación de Laravel 6