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

# Registro de rutas y caché en paquetes

> A partir de la implementación de Laravel 13, explica el papel de loadRoutesFrom, la separación de middleware y nombres, y cómo aplicar los cambios de configuración a la caché de rutas.

Cuando un paquete ofrece endpoints HTTP, no basta con que las rutas funcionen en el entorno de desarrollo: también deben funcionar con el mismo contrato después de que la aplicación que lo usa genere la caché de rutas. Si el diseño permite cambiar el prefijo de la URL o activar y desactivar las rutas mediante configuración, también hay que indicar al usuario cuándo se aplican esos cambios.

Esta página parte de los [fundamentos del desarrollo de paquetes](/es/advanced/package-development) y trata por separado el proceso de registro y el ciclo de vida de la caché. La documentación oficial de referencia es la rama por defecto de Laravel 13, `13.x`, y la implementación del framework es la última versión, `v13.34.0`.

## loadRoutesFrom solo carga el archivo

`ServiceProvider::loadRoutesFrom()` no carga el archivo de rutas si la aplicación implementa `CachesRoutes` y `routesAreCached()` devuelve verdadero. En cualquier otro caso, hace `require` del archivo indicado.

Este método no añade por sí mismo prefijos de URI ni de nombre de ruta, espacios de nombres de controladores ni middleware. Tampoco publica archivos ni añade rutas a una caché existente.

```mermaid theme={null}
flowchart TD
    A["boot del provider"] --> B["Llamar a loadRoutesFrom"]
    B --> C{"¿Hay caché de rutas?"}
    C -->|No| D["require del archivo de rutas del paquete"]
    C -->|Sí| E["Omitir la carga del archivo del paquete"]
    E --> F["El RouteServiceProvider de Laravel<br>carga la caché de la aplicación"]
```

El diagrama asume una aplicación Laravel estándar. No existe una caché exclusiva para el paquete: las rutas del paquete se incluyen en la caché de rutas de toda la aplicación.

<Warning>
  Llamar `routes/web.php` al archivo del paquete no le añade por sí solo el middleware `web`. Como la ruta de carga es distinta a la de los archivos de rutas estándar de la aplicación, declara explícitamente en el paquete el middleware que necesites.
</Warning>

## Separar la configuración del registro

En el siguiente ejemplo se crea un endpoint público que indica si el paquete puede responder. Se asume que el PSR-4 de Composer asigna `Acme\Courier\` a `src/` y que el provider se registra mediante [detección automática](/es/advanced/package-discovery) o de forma manual.

```php config/courier.php theme={null}
<?php

return [
    'routes' => [
        'enabled' => true,
        'prefix' => 'acme-courier',
    ],
];
```

La fusión de la configuración se hace en `register()` y la carga de rutas en `boot()`. No conviertas en `DeferrableProvider` un provider que registra rutas HTTP, porque dejaría de estar garantizado que el provider arranque en el momento en que se necesitan las rutas.

```php src/CourierServiceProvider.php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->mergeConfigFrom(__DIR__.'/../config/courier.php', 'courier');
    }

    public function boot(): void
    {
        if (config('courier.routes.enabled')) {
            $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
        }
    }
}
```

Esta condición solo controla el registro de rutas. Si el provider también registra otros servicios o vistas, no los coloques dentro de esta condición. Para saber cómo exponer la configuración al usuario y qué tener en cuenta al fusionar configuración anidada, consulta [Fusión y caché de la configuración de paquetes](/es/advanced/package-config-merging).

```php routes/web.php theme={null}
<?php

use Acme\Courier\Http\Controllers\StatusController;
use Illuminate\Support\Facades\Route;

Route::middleware('web')
    ->prefix(config('courier.routes.prefix'))
    ->name('acme-courier.')
    ->group(function () {
        Route::get('/status', StatusController::class)->name('status');
    });
```

```php src/Http/Controllers/StatusController.php theme={null}
<?php

namespace Acme\Courier\Http\Controllers;

use Illuminate\Http\JsonResponse;

class StatusController
{
    public function __invoke(): JsonResponse
    {
        return response()->json(['available' => true]);
    }
}
```

La URI por defecto es `/acme-courier/status` y el nombre de la ruta es `acme-courier.status`. Si generas la URL con `route('acme-courier.status')`, el código que la llama puede seguir usando el mismo nombre de ruta aunque cambie el prefijo de la URI. El `name()` del grupo concatena la cadena tal cual, así que incluye también el `.` final.

<Info>
  `web` no sustituye a la autenticación ni a la autorización. Este ejemplo es un endpoint público que no contiene información confidencial. Para los endpoints que devuelven datos del usuario, añade por separado el middleware de autenticación y la autorización que requiera la especificación.
</Info>

## Evitar por separado los conflictos de URI y de nombre de ruta

El prefijo de la URI y el prefijo del nombre de ruta son mecanismos distintos. Añadir solo uno de ellos no evita los conflictos del otro.

| Elemento | Diseño en este ejemplo | Consideraciones de mantenimiento |
| - | - | - |
| URI | `acme-courier` por defecto, modificable mediante configuración | Elegir un valor que no entre en conflicto con las URL existentes de la aplicación |
| Nombre de ruta | `acme-courier.` fijo | Usar un nombre propio del paquete y mantenerlo como contrato para generar URL |
| Controlador | Referencia a la clase | No depender del espacio de nombres de controladores de la aplicación |
| Middleware | `web` declarado explícitamente | Comprobarlo junto con la configuración de middleware de la aplicación de destino |

`AbstractRouteCollection` lanza una `LogicException` al construir la colección de rutas para la caché si otra ruta tiene el mismo nombre. Que "se haya podido generar la URL en un arranque normal" no garantiza que las rutas se puedan cachear. Incluso dos rutas con URI distintas causan problemas si comparten nombre.

No conviertas en mecanismo de extensión del paquete la sobrescritura de las rutas de la aplicación según el orden de registro. Si hace falta, ofrece una opción de configuración para desactivar las rutas y un servicio que el usuario pueda invocar desde sus propias rutas.

## La configuración del momento de crear la caché queda en la definición de rutas

`RouteCacheCommand` ejecuta primero `route:clear`, arranca una nueva aplicación y recopila las rutas. Después prepara esas rutas para que se puedan serializar y escribe el resultado compilado en el archivo de caché.

Como en ese momento también se carga el archivo de rutas del paquete, el prefijo y el hecho de registrar o no las rutas se deciden con **la configuración vigente al crear la caché**. En los arranques posteriores, `loadRoutesFrom()` no carga el archivo y se usan las rutas cacheadas.

| Cambio | Si queda una caché de rutas antigua | Acción necesaria |
| - | - | - |
| Añadir rutas al paquete | Las rutas añadidas no aparecen | Regenerar la caché de rutas |
| Cambiar `routes.prefix` | Se mantiene la URI anterior | Regenerarla con la nueva configuración |
| Cambiar `routes.enabled` a `false` | Las rutas cacheadas no desaparecen | Regenerarla con la configuración desactivada |
| Eliminar el paquete | Pueden quedar definiciones que referencian clases eliminadas | Regenerarla con la configuración posterior a la eliminación |

<Warning>
  `routes.enabled` es una opción que controla el registro, no un rechazo de acceso por petición. Si solo desactivas la configuración mientras queda una caché antigua, el endpoint no se habrá detenido.
</Warning>

No registres rutas en función de condiciones que cambian en cada petición, como el usuario o el tenant. Esas condiciones se evalúan en el entorno CLI en el momento de crear la caché. Registra las rutas con una configuración estable y decide si se permite el acceso mediante middleware o autorización dentro del controlador.

### En el despliegue, fija primero la configuración

Una vez actualizados el código y la configuración, si se usa la caché de configuración, regenera las cachés en el siguiente orden. Incorpóralo al proceso de despliegue de la aplicación que usa el paquete.

```bash theme={null}
php artisan config:cache
php artisan route:cache
php artisan route:list --name=acme-courier -vv
```

Si ejecutas `route:cache` mientras queda una caché de configuración antigua, las rutas también se generan con la configuración antigua. Volver a ejecutar solo `config:cache` no actualiza la caché de rutas. Con `-vv` también puedes comprobar el contenido de los grupos de middleware.

Si durante el desarrollo quieres comprobar el funcionamiento sin caché, limpia ambas según sea necesario.

```bash theme={null}
php artisan config:clear
php artisan route:clear
```

El archivo de rutas no se ejecuta en los arranques que usan la caché. Si registras en él listeners de eventos o bindings del contenedor, el comportamiento cambiará, así que no le des efectos secundarios distintos de la definición de rutas. En entornos con procesos de larga duración, incluye también la recarga tras actualizar la caché en el procedimiento de despliegue habitual.

## Combinaciones que comprobar antes de publicar una versión

Además de las pruebas del paquete, comprueba las siguientes combinaciones en una aplicación Laravel 13 que lo use. No te limites al registro de rutas en memoria: incluye también el camino en el que Artisan arranca una nueva aplicación.

* Sin caché, `/acme-courier/status` responde y el nombre de ruta y el middleware son los esperados.
* `route:cache` se ejecuta correctamente y, en un nuevo arranque, responde con la misma URI y el mismo nombre de ruta.
* Al cambiar el prefijo y regenerar la caché, responde la nueva URI y desaparece la ruta del paquete en la URI anterior.
* Al desactivar las rutas y regenerar la caché, la ruta no aparece en `route:list --name=acme-courier`.
* No hay conflictos de URI ni de nombre de ruta con la aplicación ni con otros paquetes.

Si también compruebas el caso en que queda una caché antigua, podrás reproducir informes de usuarios del tipo "he cambiado el archivo de configuración, pero la URL no cambia". Indica la regeneración de la caché en las instrucciones de actualización y trata también los cambios en los nombres de ruta y el middleware como cuestiones de compatibilidad.

## Páginas relacionadas

<Columns cols={2}>
  <Card title="Enrutamiento" icon="route" href="/es/routing">
    Repasa los fundamentos de los grupos de rutas, las rutas con nombre y su listado.
  </Card>

  <Card title="Fusión y caché de la configuración de paquetes" icon="sliders" href="/es/advanced/package-config-merging">
    Repasa el procedimiento de actualización teniendo en cuenta la configuración publicada y la caché de configuración.
  </Card>

  <Card title="Service providers diferidos" icon="clock" href="/es/advanced/deferred-provider">
    Repasa por qué no conviene diferir un provider que registra rutas.
  </Card>

  <Card title="Gestión de la compatibilidad de versiones de paquetes" icon="code-branch" href="/es/advanced/package-versioning">
    Vincula los cambios en la API pública con la política de versiones y la verificación continua.
  </Card>
</Columns>

## Fuentes primarias consultadas

* [Documentación oficial de Laravel: rutas de paquetes](https://github.com/laravel/docs/blob/156fc7fde114548640e13c39aa79b991291c3f91/packages.md#routes)
* [Documentación oficial de Laravel: enrutamiento](https://github.com/laravel/docs/blob/156fc7fde114548640e13c39aa79b991291c3f91/routing.md)
* [ServiceProvider: implementación de loadRoutesFrom](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Support/ServiceProvider.php)
* [RouteServiceProvider: carga de la caché](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php)
* [RouteCacheCommand: recopilación y guardado en una nueva aplicación](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/RouteCacheCommand.php)
* [AbstractRouteCollection: detección de nombres de ruta duplicados](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Routing/AbstractRouteCollection.php)


## Related topics

- [Desarrollo de paquetes para Laravel](/es/advanced/package-development.md)
- [Temas avanzados](/es/advanced/index.md)
- [Sobrescritura y actualización de vistas de paquetes](/es/advanced/package-views.md)
- [Desarrollar paquetes con Testbench Workbench](/es/advanced/package-workbench.md)
- [Service providers diferidos](/es/advanced/deferred-provider.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.