1. Conceptos básicos
  2. Generación de URL

Únete a nuestra comunidad de Telegram @webblend!

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

Introducción

Laravel proporciona varios ayudantes para ayudarte a generar URL para tu aplicación. Estos ayudantes son especialmente útiles al construir enlaces en tus plantillas y respuestas de API, o al generar respuestas de redirección a otra parte de tu aplicación.

Lo básico

Generación de URL

El ayudante url se puede usar para generar URL arbitrarias para tu aplicación. La URL generada usará automáticamente el esquema (HTTP o HTTPS) y el host de la solicitud actual que está siendo manejada por la aplicación:

$post = App\Models\Post::find(1);
 
echo url("/posts/{$post->id}");
 
// http://example.com/posts/1

Acceso a la URL actual

Si no se proporciona ninguna ruta al ayudante url, se devuelve una instancia de Illuminate\Routing\UrlGenerator, lo que te permite acceder a la información sobre la URL actual:

// Obtener la URL actual sin la cadena de consulta...
echo url()->current();
 
// Obtener la URL actual incluyendo la cadena de consulta...
echo url()->full();
 
// Obtener la URL completa de la solicitud anterior...
echo url()->previous();

Cada uno de estos métodos también se puede acceder mediante el facade URL:

use Illuminate\Support\Facades\URL;
 
echo URL::current();

URLs para rutas con nombre

El ayudante route se puede usar para generar URL a rutas con nombre. Las rutas con nombre te permiten generar URL sin estar acoplado a la URL real definida en la ruta. Por lo tanto, si la URL de la ruta cambia, no es necesario realizar cambios en tus llamadas a la función route. Por ejemplo, imagina que tu aplicación contiene una ruta definida de la siguiente manera:

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

Para generar una URL a esta ruta, puedes usar el ayudante route de la siguiente manera:

echo route('post.show', ['post' => 1]);
 
// http://example.com/post/1

Por supuesto, el ayudante route también se puede usar para generar URL para rutas con varios parámetros:

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

Cualquier elemento adicional del array que no corresponda a los parámetros de definición de la ruta se agregará a la cadena de consulta de la URL:

echo route('post.show', ['post' => 1, 'search' => 'rocket']);
 
// http://example.com/post/1?search=rocket

Modelos Eloquent

A menudo, generarás URL utilizando la clave de ruta (típicamente la clave primaria) de modelos Eloquent. Por esta razón, puedes pasar modelos Eloquent como valores de parámetros. El ayudante route extraerá automáticamente la clave de ruta del modelo:

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

URLs firmadas

Laravel te permite crear fácilmente URLs "firmadas" para rutas con nombre. Estas URLs tienen un hash de "firma" agregado a la cadena de consulta que permite a Laravel verificar que la URL no ha sido modificada desde que se creó. Las URLs firmadas son especialmente útiles para rutas que son accesibles públicamente pero necesitan una capa de protección contra la manipulación de URL.

Por ejemplo, podrías usar URLs firmadas para implementar un enlace público "darse de baja" que se envía por correo electrónico a tus clientes. Para crear una URL firmada a una ruta con nombre, usa el método signedRoute del facade URL:

use Illuminate\Support\Facades\URL;
 
return URL::signedRoute('unsubscribe', ['user' => 1]);

Puedes excluir el dominio del hash de la URL firmada proporcionando el argumento absolute al método signedRoute:

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

Si deseas generar una URL de ruta firmada temporal que caduque después de un tiempo especificado, puedes usar el método temporarySignedRoute. Cuando Laravel valida una URL de ruta temporal firmada, se asegurará de que la marca de tiempo de vencimiento codificada en la URL firmada no haya transcurrido:

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

Validación de solicitudes de ruta firmadas

Para verificar que una solicitud entrante tiene una firma válida, debes llamar al método hasValidSignature en la instancia entrante de Illuminate\Http\Request:

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

A veces, es posible que necesites permitir que el frontend de tu aplicación agregue datos a una URL firmada, como al realizar paginación del lado del cliente. Por lo tanto, puedes especificar los parámetros de consulta de la solicitud que deben ignorarse al validar una URL firmada mediante el método hasValidSignatureWhileIgnoring. Recuerda, ignorar parámetros permite a cualquiera modificar esos parámetros en la solicitud:

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

En lugar de validar las URL firmadas mediante la instancia entrante de la solicitud, puedes asignar el middleware Illuminate\Routing\Middleware\ValidateSignature a la ruta. Si aún no está presente, puedes asignarle un alias a este middleware en el array $middlewareAliases de tu kernel HTTP:

/**
* Los alias de middleware de la aplicación.
*
* Los alias se pueden usar para asignar middleware convenientemente a rutas y grupos.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'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 HTTP 403:

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

Si tus URL firmadas no incluyen el dominio en el hash de la URL, debes proporcionar el argumento relative al middleware:

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

Respuestas a rutas firmadas no válidas

Cuando alguien visita una URL firmada que ha caducado, recibirá una página de error genérica para el código de estado HTTP 403. Sin embargo, puedes personalizar este comportamiento definiendo un cierre de "renderizable" personalizado para la excepción InvalidSignatureException en tu manejador de excepciones. Este cierre debería devolver una respuesta HTTP:

use Illuminate\Routing\Exceptions\InvalidSignatureException;
 
/**
* Registra las devoluciones de llamada para el manejo de excepciones en la aplicación.
*/
public function register(): void
{
$this->renderable(function (InvalidSignatureException $e) {
return response()->view('error.link-expired', [], 403);
});
}

URLs para acciones de controladores

La función action genera una URL para la acción de controlador dada:

use App\Http\Controllers\HomeController;
 
$url = action([HomeController::class, 'index']);

Si el método del controlador acepta parámetros de ruta, puedes pasar un array asociativo de parámetros de ruta como segundo argumento a la función:

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

Valores predeterminados

Para algunas aplicaciones, es posible que desees especificar valores predeterminados para ciertos parámetros de URL en toda la solicitud. Por ejemplo, imagina que muchas de tus rutas definen un parámetro {locale}:

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

Es engorroso tener que pasar siempre el locale cada vez que llamas al ayudante route. Entonces, puedes usar el método URL::defaults para definir un valor predeterminado para este parámetro que siempre se aplicará durante la solicitud actual. Puedes llamar a este método desde un middleware de ruta para tener acceso a la solicitud actual:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;
 
class SetDefaultLocaleForUrls
{
/**
* Maneja una 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);
}
}

Una vez que se ha establecido el valor predeterminado para el parámetro locale, ya no es necesario pasar su valor al generar URL mediante el ayudante route.

Valores predeterminados de URL y prioridad del middleware

Establecer valores predeterminados de URL puede interferir con el manejo de las vinculaciones de modelos implícitas de Laravel. Por lo tanto, debes priorizar tu middleware que establece valores predeterminados de URL para que se ejecute antes del propio middleware SubstituteBindings de Laravel. Puedes lograr esto asegurándote de que tu middleware ocurra antes del middleware SubstituteBindings dentro de la propiedad $middlewarePriority del kernel HTTP de tu aplicación.

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

/**
* La lista de middleware ordenada por prioridad.
*
* Esto fuerza a que el middleware no global siempre esté en el orden dado.
*
* @var array
*/
protected $middlewarePriority = [
// ...
\App\Http\Middleware\SetDefaultLocaleForUrls::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// ...
];