# Introducción

Laravel incorpora varias funciones de asistencia en la generación de URLs. Por supuesto, son principalmente útiles para la generación de enlaces en las vistas y respuestas API, o para generar redirecciones a otra parte de la aplicación.

# Lo básico

Generar URL's Básicas

La función url se puede utilizar para generar URLs de la aplicación. Estas URLs utilizarán directamente el esquema HTTP o HTTPS y host de la petición:

$post = App\Models\Post::find(1);

echo url("/posts/{$post->id}");

// http://example.com/posts/1

Acceder a la URL actual

Si no se especifica un directorio a la función url, se retornará una instancia de Illuminate\Routing\UrlGenerator, permitiendo acceder a información sobre la URL actual:

// Get the current URL without the query string...
echo url()->current();

// Get the current URL including the query string...
echo url()->full();

// Get the full URL for the previous request...
echo url()->previous();

Cada uno de estos métodos se puede acceder también a través de URL como facade:

use Illuminate\Support\Facades\URL;

echo URL::current();

# URL de rutas con nombre

La función route genera URLs a rutas con nombre. Las rutas con nombre permiten generar URLs desacopladas de la URL definida en la ruta. Por lo tanto, si la URL de la ruta cambia, no es necesario modificar las llamadas a la función route. Por ejemplo, imaginar una aplicación que contiene la siguiente ruta:

Route::get('/post/{post}', function () {
    //
})->name('post.show');

Para generar una URL a esta ruta se usaría la función route de este modo:

echo route('post.show', ['post' => 1]);

// http://example.com/post/1

Cualquier parámetro adicional del conjunto que no corresponda a los parámetros de definición de la ruta se añadirá a la cadena de consulta del URL:

echo route('post.show', ['post' => 1, 'search' => 'rocket']);

// http://example.com/post/1?search=rocket

A menudo se generarán URLs utilizando la clave primaria de un modelo Eloquent. Por esta razón, se pueden pasar modelos Eloquent como parámetro. La función route extraerá directamente la clave primaria del modelo:

echo route('post.show', ['post' => $post]);

El helper route también puede utilizarse para generar URLs para rutas con múltiples parámetros:

Route::get('/post/{post}/comment/{comment}', function () {
    //
})->name('comment.show');

echo route('comment.show', ['post' => 1, 'comment' => 3]);

// http://example.com/post/1/comment/3

Signed URLs

Laravel te permite crear fácilmente URLs "firmadas" para rutas con nombre. Estos URLs tienen un hash de "firma" adjunto a la cadena de consulta que permite a Laravel verificar que el URL no ha sido modificado desde que fue creado. Los URLs firmados son especialmente útiles para las rutas que son de acceso público pero que necesitan una capa de protección contra la manipulación de los URLs.

Por ejemplo, puede utilizar URLs firmadas para implementar un enlace público de "cancelación de suscripción" que se envía por correo electrónico a sus clientes. Para crear una URL firmada a una ruta con nombre, utilice el método "signedRoute" de la fachada "URL":

use Illuminate\Support\Facades\URL;

return URL::signedRoute('unsubscribe', ['user' => 1]);

Si desea generar una URL de ruta firmada temporal que expire, puede utilizar el método temporarySignedRoute:

use Illuminate\Support\Facades\URL;

return URL::temporarySignedRoute(
    'unsubscribe', now()->addMinutes(30), ['user' => 1]
);

Validación de las solicitudes de ruta firmadas

Para verificar que una solicitud entrante tiene una firma válida, debe llamar al método hasValidSignature en la Request entrante:

use Illuminate\Http\Request;

Route::get('/unsubscribe/{user}', function (Request $request) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }

    // ...
})->name('unsubscribe');

Alternativamente, puede asignar el middleware Illuminate\Routing\Middleware\ValidateSignature a la ruta. Si no está ya presente, debería asignar a este middleware una clave en el array routeMiddleware de su kernel HTTP::

/**
 * The application's route middleware.
 *
 * These middleware may be assigned to groups or used individually.
 *
 * @var array
 */
protected $routeMiddleware = [
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];

Una vez que hayas registrado el middleware en tu kernel, puedes adjuntarlo a una ruta. Si la solicitud entrante no tiene una firma válida, el middleware devolverá automáticamente una respuesta de error 403:

Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed');

# URLs a Acciones de Controlladores

La función action genera un URL para la acción del controlador dado:

use App\Http\Controllers\HomeController;

$url = action([HomeController::class, 'index']);

Si el método de control acepta parámetros de ruta, puede pasarlos como segundo argumento a la función:

$url = action([UserController::class, 'profile'], ['id' => 1]);

# Valores por defecto

Para algunas aplicaciones, se pueden especificar valores por defecto para ciertos parámetros URL. Por ejemplo, imaginar que muchas de las rutas definen un parámetro {locale}:

Route::get('/{locale}/posts', function () {
    //
})->name('post.index');

Es tedioso ir pasando locale cada vez que se llama a la función route. Se puede utilizar el método URL::defaults para definir un valor por defecto para este parámetro que será aplicado siempre durante la petición actual. Se puede llamar a este método desde un route middleware (middleware de ruta) por lo que se tendrá acceso a la petición actual:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\URL;

class SetDefaultLocaleForUrls
{
    public function handle($request, Closure $next)
    {
        URL::defaults(['locale' => $request->user()->locale]);

        return $next($request);
    }
}

Una vez que el valor por defecto para locale se ha establecido, no será necesario pasarlo más al generar URLs a través del helper route.

Valores predeterminados de la URL y prioridad del middleware

Establecer los valores por defecto de la URL puede interferir con el manejo de Laravel de los enlaces de modelos implícitos. Por lo tanto, deberías priorizar su middleware que establece los valores por defecto de la URL para ser ejecutados antes del propio middleware SubstituteBindings de Laravel. Puede lograr esto asegurándose de que su middleware se produce antes que el middleware SubstituteBindings dentro de la propiedad $middlewarePriority del kernel HTTP de su aplicación.

La propiedad $middlewarePriority se define en la clase base Illuminate\Foundation\Http\Kernel. Puedes copiar su definición de esa clase y sobreescribirla en el kernel HTTP de tu aplicación para modificarla:

/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    // ...
     \App\Http\Middleware\SetDefaultLocaleForUrls::class,
     \Illuminate\Routing\Middleware\SubstituteBindings::class,
     // ...
];