> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Generación de URLs

> Explicamos cómo generar URLs con el helper url() de Laravel, URLs de rutas con nombre, URLs firmadas y URLs a acciones de controlador.

## Introducción

Laravel proporciona varios helpers para generar URLs de tu aplicación.
Son especialmente útiles al construir enlaces en plantillas o respuestas de API, o al generar respuestas de redirección a otra parte de la aplicación.

## Uso básico

### Generar URLs

Con el helper `url` puedes generar cualquier URL.
La URL generada utiliza automáticamente el esquema (HTTP o HTTPS) y el host de la solicitud actual.

```php theme={null}
$post = App\Models\Post::find(1);

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

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

Para generar una URL con parámetros de query string, usa el método `query`.

```php theme={null}
echo url()->query('/posts', ['search' => 'Laravel']);

// https://example.com/posts?search=Laravel

echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);

// http://example.com/posts?sort=latest&search=Laravel
```

Si indicas parámetros de query que ya existen en la ruta, se sobrescriben los valores existentes.

```php theme={null}
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);

// http://example.com/posts?sort=oldest
```

También puedes pasar valores como array. Estos valores se indexan correctamente y se codifican en la URL generada.

```php theme={null}
echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);

// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body

echo urldecode($url);

// http://example.com/posts?columns[0]=title&columns[1]=body
```

### Obtener la URL actual

Si no pasas una ruta al helper `url`, se devuelve una instancia de `Illuminate\Routing\UrlGenerator` que da acceso a información sobre la URL actual.

```php theme={null}
// URL actual sin query string
echo url()->current();

// URL actual con query string
echo url()->full();
```

También puedes acceder a estos métodos con la [fachada](./facades) `URL`.

```php theme={null}
use Illuminate\Support\Facades\URL;

echo URL::current();
```

### Obtener la URL anterior

A veces querrás saber la URL que visitaba el usuario justo antes. Puedes obtenerla con `previous` o `previousPath` del helper `url`.

```php theme={null}
// URL completa de la solicitud anterior
echo url()->previous();

// Ruta de la solicitud anterior
echo url()->previousPath();
```

También puedes obtenerla a través de la sesión.

```php theme={null}
use Illuminate\Http\Request;

Route::post('/users', function (Request $request) {
    $previousUri = $request->session()->previousUri();

    // ...
});
```

Y también el nombre de ruta de la última URL visitada.

```php theme={null}
$previousRoute = $request->session()->previousRoute();
```

## URLs de rutas con nombre

El helper `route` sirve para generar URLs de [rutas con nombre](./routing#named-routes).
Con rutas con nombre puedes generar URLs sin depender de la URL real definida en la ruta.
Así, aunque la URL cambie, no necesitas modificar las llamadas a `route`.

```php theme={null}
Route::get('/post/{post}', function (Post $post) {
    // ...
})->name('post.show');
```

Genera la URL a esta ruta así:

```php theme={null}
echo route('post.show', ['post' => 1]);

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

También funciona con rutas de varios parámetros.

```php theme={null}
Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
    // ...
})->name('comment.show');

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

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

Los elementos del array que no coincidan con parámetros de la ruta se añaden como query string.

```php theme={null}
echo route('post.show', ['post' => 1, 'search' => 'rocket']);

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

### Modelos Eloquent

Es habitual generar URLs con la clave de ruta (normalmente la clave primaria) de un modelo Eloquent.
Puedes pasar el modelo directamente como parámetro. `route` extraerá automáticamente la clave de ruta del modelo.

```php theme={null}
echo route('post.show', ['post' => $post]);
```

### URLs firmadas

Laravel facilita la creación de URLs "firmadas" a rutas con nombre.
A la URL se le añade un hash de "firma" en el query string, lo que permite a Laravel comprobar que la URL no ha sido manipulada tras su creación.
Las URLs firmadas son muy útiles en rutas de acceso público que necesitan protección frente a manipulación.

Por ejemplo, puedes usar URLs firmadas para implementar un enlace público de "cancelar suscripción" que envías por correo.
Créalas con `signedRoute` de la fachada `URL`.

```php theme={null}
use Illuminate\Support\Facades\URL;

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

Con el argumento `absolute` de `signedRoute` puedes excluir el dominio del hash de firma.

```php theme={null}
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
```

Para generar una URL firmada temporal que caduque tras un tiempo dado, usa `temporarySignedRoute`.
Al validar una URL firmada temporal, Laravel comprueba que el timestamp de caducidad codificado en la URL no haya pasado.

```php theme={null}
use Illuminate\Support\Facades\URL;

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

#### Flujo de verificación de la URL firmada

```mermaid theme={null}
sequenceDiagram
    participant App as Aplicación Laravel
    participant User as Usuario
    participant Mail as Correo
    App->>App: URL::signedRoute() / temporarySignedRoute()
    App->>Mail: Envío del correo con la URL firmada
    Mail->>User: Recepción del correo
    User->>App: El usuario pulsa la URL (GET)
    App->>App: Verificación de firma<br>hasValidSignature()
    alt Firma válida
        App->>User: Ejecuta la acción (por ejemplo, cancelar suscripción)
    else Firma no válida o caducada
        App->>User: Error 403
    end
```

#### Verificar solicitudes con ruta firmada

Para comprobar que la solicitud entrante tiene una firma válida, llama a `hasValidSignature` sobre la instancia `Illuminate\Http\Request`.

```php theme={null}
use Illuminate\Http\Request;

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

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

Si quieres ignorar ciertos parámetros del query string al validar, usa `hasValidSignatureWhileIgnoring`.

```php theme={null}
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
    abort(401);
}
```

En lugar de la instancia de la solicitud, puedes asignar el [middleware](./middleware) `signed` (`Illuminate\Routing\Middleware\ValidateSignature`) a la ruta.
Si la solicitud no tiene una firma válida, el middleware responde automáticamente con `403`.

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

Si la URL firmada no incluye el dominio, indícalo con el argumento `relative` en el middleware.

```php theme={null}
Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed:relative');
```

#### Respuesta a rutas firmadas no válidas

Cuando se accede a una URL firmada caducada, se muestra una página de error genérica con código HTTP `403`.
Puedes personalizar este comportamiento definiendo un closure de "render" para la excepción `InvalidSignatureException` en `bootstrap/app.php`.

```php theme={null}
use Illuminate\Routing\Exceptions\InvalidSignatureException;

->withExceptions(function (Exceptions $exceptions): void {
    $exceptions->render(function (InvalidSignatureException $e) {
        return response()->view('errors.link-expired', status: 403);
    });
})
```

## URLs de acciones de controlador

La función `action` genera la URL de una acción de controlador determinada.

```php theme={null}
use App\Http\Controllers\HomeController;

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

Si el método del controlador recibe parámetros de ruta, pasa un array asociativo como segundo argumento.

```php theme={null}
$url = action([UserController::class, 'profile'], ['id' => 1]);
```

## Objeto URI fluido

La clase URI de Laravel proporciona una interfaz fluida para crear y manipular URIs mediante objetos.

```php theme={null}
use App\Http\Controllers\UserController;
use Illuminate\Support\Uri;

// Crear una instancia URI desde un string
$uri = Uri::of('https://example.com/path');

// Generar un URI a una ruta, ruta con nombre o acción de controlador
$uri = Uri::to('/dashboard');
$uri = Uri::route('users.show', ['user' => 1]);
$uri = Uri::signedRoute('users.show', ['user' => 1]);
$uri = Uri::temporarySignedRoute('user.index', now()->plus(minutes: 5));
$uri = Uri::action([UserController::class, 'index']);

// Crear una instancia URI desde la URL de la solicitud actual
$uri = $request->uri();
```

Una vez obtenida la instancia, puedes modificarla de forma fluida.

```php theme={null}
$uri = Uri::of('https://example.com')
    ->withScheme('http')
    ->withHost('test.com')
    ->withPort(8000)
    ->withPath('/users')
    ->withQuery(['page' => 2])
    ->withFragment('section-1');
```

## Parámetros de URL por defecto

A veces querrás fijar un valor por defecto para ciertos parámetros de URL en toda la solicitud.
Por ejemplo, imagina que muchas rutas tienen un parámetro `{locale}`.

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

Pasar `locale` cada vez que se llama a `route` resulta pesado.
Con `URL::defaults` puedes definir un valor por defecto de este parámetro que se aplique durante toda la solicitud actual.
Llamando a este método desde un [middleware de ruta](./middleware#assigning-middleware-to-routes) puedes acceder a la solicitud actual.

```php theme={null}
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;

class SetDefaultLocaleForUrls
{
    /**
     * Procesa la solicitud entrante.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        URL::defaults(['locale' => $request->user()->locale]);

        return $next($request);
    }
}
```

Con el valor por defecto de `locale` establecido, ya no hace falta pasarlo al generar URLs con `route`.

<Info>
  Establecer valores por defecto puede interferir con el implicit model binding de Laravel.
  Ordena las prioridades del middleware para que el que establece los defaults se ejecute antes que el `SubstituteBindings` de Laravel.
  Puedes configurar la [prioridad del middleware](./middleware#sorting-middleware) con el método `priority` en `bootstrap/app.php`.

  ```php theme={null}
  ->withMiddleware(function (Middleware $middleware): void {
      $middleware->prependToPriorityList(
          before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
          prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
      );
  })
  ```
</Info>


## Related topics

- [Enrutamiento](/es/routing.md)
- [Funciones auxiliares](/es/helpers.md)
- [Guía de desarrollo de apps con integración de la Engine API - VOICEVOX for Laravel](/es/packages/laravel-voicevox/app-guide.md)
- [Almacenamiento de archivos](/es/filesystem.md)
- [Presentación de Laravel Wayfinder](/es/blog/wayfinder-introduction.md)
