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

# Fusión y caché de la configuración de paquetes

> A partir de la implementación de ServiceProvider en Laravel 13, explica la diferencia entre la fusión superficial y el reemplazo recursivo, los riesgos de los arrays con claves numéricas y cómo mantener un paquete teniendo en cuenta la caché de configuración.

Añadir opciones a la configuración de tu paquete no escribe automáticamente las nuevas claves en los archivos de configuración que los usuarios ya hayan publicado. Para completar los valores por defecto sin romper la configuración publicada, debes diseñar tanto la estrategia de fusión de arrays como el comportamiento con la caché de configuración.

Esta página analiza el `ServiceProvider` de Laravel 13 y resume cómo mantener la configuración como parte de la API pública de tu paquete. Se da por supuesto que conoces los [fundamentos del desarrollo de paquetes](/es/advanced/package-development), y la implementación se ha verificado con la versión `v13.34.0` de `laravel/framework`.

## Publicar y fusionar son procesos distintos

`publishes()` registra un origen y un destino de copia. Hasta que `vendor:publish` copia el archivo, el directorio `config` del usuario no cambia. Por su parte, `mergeConfigFrom()` actualiza el repositorio de configuración durante el arranque y no modifica el archivo en sí.

```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
    {
        $this->publishes([
            __DIR__.'/../config/courier.php' => config_path('courier.php'),
        ], 'courier-config');
    }
}
```

El usuario publica el archivo de configuración solo cuando lo necesita. Aunque no lo publique, en un arranque normal sin caché se usan los valores por defecto gracias a la fusión de `register()`.

```bash theme={null}
php artisan vendor:publish --tag=courier-config
```

<Warning>
  Si como paso de actualización vuelves a publicar el archivo de configuración con `--force`, sobrescribirás las modificaciones del usuario. Si solo añades nuevas opciones de configuración, prioriza completar los valores por defecto y comunicar los cambios.
</Warning>

## mergeConfigFrom() solo fusiona el nivel superior

`ServiceProvider::mergeConfigFrom()` ejecuta `array_merge()` pasando primero la configuración del paquete y después la configuración existente de la aplicación. Para una misma clave de tipo cadena, prevalece el valor de la aplicación.

El siguiente ejemplo reproduce el proceso de fusión del framework usando solo arrays.

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

$defaults = [
    'enabled' => true,
    'transport' => [
        'timeout' => 10,
        'retries' => 3,
    ],
];

$overrides = [
    'transport' => [
        'timeout' => 30,
    ],
];

$config = array_merge($defaults, $overrides);

var_export($config);
```

```text theme={null}
array (
  'enabled' => true,
  'transport' =>
  array (
    'timeout' => 30,
  ),
)
```

La clave de nivel superior `enabled` se completa, pero el array `transport` se reemplaza por completo y `transport.retries` desaparece. Lo importante es que, si el usuario ya publicó un array `transport` antiguo, las nuevas claves que añadas a ese mismo array no se completarán.

## Completar la configuración anidada con replaceConfigRecursivelyFrom()

El `ServiceProvider` de Laravel 13 también incluye el método protegido `replaceConfigRecursivelyFrom()`, que ejecuta `array_replace_recursive()` con el mismo orden de argumentos.

Si quieres que tu API de configuración permita sobrescribir individualmente las claves de tipo cadena anidadas, cambia el método `register()` del provider de la siguiente manera. No necesitas combinarlo con el `mergeConfigFrom()` anterior para la misma clave de configuración.

```php theme={null}
public function register(): void
{
    $this->replaceConfigRecursivelyFrom(
        __DIR__.'/../config/courier.php', 'courier'
    );
}
```

Con los mismos `$defaults` y `$overrides` de antes, el resultado es el siguiente.

```php theme={null}
$config = array_replace_recursive($defaults, $overrides);

var_export($config);
```

```text theme={null}
array (
  'enabled' => true,
  'transport' =>
  array (
    'timeout' => 30,
    'retries' => 3,
  ),
)
```

| Contrato de configuración | Proceso a elegir | Precaución |
| - | - | - |
| El usuario especifica los arrays anidados completos | `mergeConfigFrom()` | Las claves no especificadas dentro del array no se completan |
| El usuario especifica solo una parte de los elementos anidados | `replaceConfigRecursivelyFrom()` | Las listas con claves numéricas también se reemplazan recursivamente |

<Info>
  `replaceConfigRecursivelyFrom()` es un método que existe en el código fuente de Laravel 13 revisado en esta página. Distínguelo de `mergeConfigFrom()`, que es el que presenta la documentación oficial de desarrollo de paquetes, y comprueba la implementación del framework correspondiente antes de usarlo.
</Info>

### Las listas con claves numéricas no se reemplazan por completo

El reemplazo recursivo no consiste en "sustituir todo el array por los valores del usuario". También con claves numéricas, reemplaza el valor de la misma clave y conserva las claves que el usuario no haya especificado.

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

$defaults = ['channels' => ['mail', 'database']];
$overrides = ['channels' => ['slack']];

$config = array_replace_recursive($defaults, $overrides);

var_export($config['channels']);
```

```text theme={null}
array (
  0 => 'slack',
  1 => 'database',
)
```

Aunque el usuario especifique solo `['slack']`, `database` se mantiene. Además, pasar `['channels' => []]` no vacía la lista por defecto. Presta especial atención en configuraciones donde especificar la lista completa tiene significado, como los destinos de notificación o los middleware.

Si tienes configuraciones de este tipo, revisa la estructura de la configuración, por ejemplo separando las listas y los arrays asociativos que admiten sobrescritura parcial en claves de nivel superior distintas y usando la fusión superficial. Si cambias el método de fusión en un paquete ya publicado, el mismo archivo de configuración se comportará de forma diferente, así que no lo trates como un simple cambio de implementación.

## La caché de configuración guarda los valores ya fusionados

Ambos métodos omiten el proceso de fusión cuando la aplicación implementa `CachesConfiguration` y `configurationIsCached()` devuelve `true`. En una aplicación Laravel normal, esto ocurre en los arranques en los que existe una caché de configuración.

`ConfigCacheCommand` elimina la caché de configuración antigua, arranca una nueva aplicación y obtiene el repositorio de configuración completo. En ese arranque se fusiona la configuración de los providers y el resultado se guarda en el archivo de caché. En los arranques posteriores, `LoadConfiguration` carga esos valores.

```mermaid theme={null}
flowchart TD
    A["php artisan config:cache"] --> B["Eliminar la caché de configuración antigua"]
    B --> C["Arrancar una nueva aplicación"]
    C --> D["Cargar los archivos de configuración<br>Fusionar en los providers"]
    D --> E["Guardar todo el repositorio de configuración"]
    E --> F["Los arranques posteriores usan la configuración guardada<br>Ambos métodos de fusión se omiten"]
```

Por lo tanto, aunque actualices el paquete y cambien los valores por defecto o el método de fusión, las aplicaciones que sigan usando una caché antigua no reflejarán esos cambios. En los despliegues que usan caché de configuración, reconstrúyela con el código actualizado.

```bash theme={null}
php artisan config:cache
```

Si durante el desarrollo quieres volver a leer la configuración desde los archivos, usa `php artisan config:clear`. No decidas por tu cuenta la ubicación de la caché; deja su gestión a los comandos de Laravel.

<Warning>
  No definas Closures en los archivos de configuración, ya que `config:cache` no puede serializarlos correctamente. Si necesitas pasar un callback, coloca en la configuración un nombre de clase u otro valor similar y registra el servicio real en el provider.
</Warning>

## Comprobaciones antes de publicar cambios de configuración

En las pruebas del paquete, usa como entrada no solo la configuración sin publicar, sino también la configuración que se conserva de versiones anteriores.

* Aunque la configuración no esté publicada, se obtienen los valores por defecto necesarios.
* Con una configuración publicada antigua, los valores del usuario prevalecen y las nuevas opciones se completan según lo diseñado.
* El contrato de sobrescritura no cambia para arrays anidados, listas con claves numéricas y arrays vacíos.
* `config:cache` se ejecuta correctamente en la aplicación que usa el paquete, y otro arranque que usa la caché obtiene la misma configuración.

Indica en las notas de la versión los valores por defecto de las nuevas claves y cualquier reconstrucción de caché necesaria. Al eliminar o renombrar claves, o al cambiar el método de fusión, evalúa también la compatibilidad con la configuración que los usuarios ya hayan publicado.

## Páginas relacionadas

<Columns cols={2}>
  <Card title="Pruebas de paquetes" icon="flask" href="/es/advanced/package-testing">
    Registra el service provider y verifica el comportamiento de la configuración y los servicios.
  </Card>

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

## Fuentes primarias consultadas

* [Documentación oficial de Laravel: configuración de paquetes](https://github.com/laravel/docs/blob/13.x/packages.md#configuration)
* [ServiceProvider: implementación de la fusión y la publicación](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Support/ServiceProvider.php)
* [ConfigCacheCommand: generación de la caché de configuración](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ConfigCacheCommand.php)
* [LoadConfiguration: carga de la configuración](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php)
* [ConfigClearCommand: eliminación de la caché de configuración](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ConfigClearCommand.php)


## Related topics

- [Desarrollo de paquetes para Laravel](/es/advanced/package-development.md)
- [Temas avanzados](/es/advanced/index.md)
- [Configuración](/es/configuration.md)
- [Estructura interna de la detección automática de paquetes](/es/advanced/package-discovery.md)
- [Gestión de la compatibilidad de versiones de paquetes](/es/advanced/package-versioning.md)


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