Domain Config¶
El módulo Domain Config proporciona sobrescrituras de configuración por dominio. Permite que cada dominio tenga su propio nombre de sitio, configuración de tema, página de inicio por defecto o cualquier otra configuración — todo desde una única instalación de Drupal.
Este módulo solo cubre las sobrescrituras por dominio. Las sobrescrituras
por idioma que se añaden encima (indexadas por la pareja
(domain, langcode)) las proporciona el submódulo opcional
Domain Config Language, donde se
describen.
Arquitectura: 2.x vs 3.x¶
Domain Config 3.x es un rediseño completo de cómo se almacenan y resuelven las sobrescrituras de configuración por dominio. La versión 2.x utilizaba una solución interna personalizada, mientras que 3.x aprovecha la Config Collections API nativa de Drupal.
El enfoque 2.x (legacy)¶
En Domain 2.x, las sobrescrituras por dominio se almacenaban como objetos de configuración separados en la colección por defecto, usando una convención de nombres:
domain.config.{domain_id}.{config_name}
Por ejemplo, sobrescribir el nombre del sitio en one_example_com:
domain.config.one_example_com.system.site
Estos objetos vivían junto a toda la demás configuración en el almacenamiento por defecto. En tiempo de ejecución, un resolver personalizado interceptaba las cargas de configuración, detectaba el dominio activo, construía el nombre de la sobrescritura, intentaba cargarla y fusionaba el resultado sobre la configuración base.
Limitaciones de este enfoque:
- Los objetos de configuración contaminaban el espacio de nombres de la colección por defecto.
- El esquema de nombres era frágil — la expresión regular para extraer el ID de dominio y el nombre de configuración de una cadena plana era propensa a errores.
- Sin integración con
ConfigFactoryOverrideInterfacede Drupal — el mecanismo de sobrescritura era completamente personalizado. - La exportación/importación de configuración no entendía estos elementos como sobrescrituras — aparecían como objetos de configuración regulares.
- Los eventos de configuración (save, delete, rename) requerían propagación manual.
El enfoque 3.x (config collections)¶
Domain Config 3.x almacena las sobrescrituras en colecciones de configuración de Drupal — una funcionalidad nativa de Drupal diseñada exactamente para este propósito. Las colecciones son particiones virtuales del almacenamiento de configuración que comparten el mismo backend (sistema de archivos, base de datos, etc.) pero están lógicamente separadas.
Nomenclatura de colecciones:
| Tipo | Formato | Ejemplo |
|---|---|---|
| Solo dominio | domain.{domain_id} |
domain.one_example_com |
Dentro de una colección, el objeto de configuración conserva su nombre
original. Por ejemplo, la sobrescritura del nombre del sitio para
one_example_com se almacena como system.site dentro de la colección
domain.one_example_com — no como un nombre aplanado modificado.
Beneficios clave:
- Separación limpia entre la configuración base y las sobrescrituras.
- API estándar de Drupal (
ConfigFactoryOverrideInterface). - Soporte adecuado de exportación/importación de configuración — las colecciones se exportan como subdirectorios.
- Los eventos de configuración (save, delete, rename) se gestionan automáticamente.
El submódulo opcional
Domain Config Language añade una
segunda colección (domain.{domain_id}.language.{lang_code}) encima de
la de por dominio, para los sitios que necesitan sobrescrituras
indexadas tanto por dominio como por idioma.
Cómo funciona en tiempo de ejecución¶
Resolución de sobrescrituras¶
Cuando Drupal carga un objeto de configuración (por ejemplo,
system.site), la config factory solicita a todos los servicios de
sobrescritura registrados que proporcionen sus sobrescrituras. Domain
Config registra un servicio de sobrescritura:
domain.config_factory_override(prioridad -253) — carga la sobrescritura por dominio desde la coleccióndomain.{domain_id}.
El resultado final fusionado sigue esta cascada:
Configuración base (colección por defecto)
↓ fusionada con
Sobrescritura por dominio (colección domain.{domain_id})
= Configuración final en tiempo de ejecución
Ejemplo con system.site en el dominio two_example_com:
# Configuración base (colección por defecto):
system.site:
name: "My Site"
# Sobrescritura por dominio (colección domain.two_example_com):
system.site:
name: "Two" # sobrescribe "My Site" → "Two"
# Resultado final en tiempo de ejecución: name = "Two"
Cuando domain_config_language también está instalado, una capa
adicional (domain, langcode) se añade a esta cascada — véase la
documentación de Domain Config Language.
Contexto de dominio¶
El dominio activo se determina mediante DomainNegotiationContext, que
se inyecta en el servicio de sobrescritura. El contexto se establece
durante el evento kernel request por DomainSubscriber y también
puede cambiarse programáticamente (por ejemplo, por Domain Config al
comparar configuraciones entre dominios).
Cuando no hay un dominio activo (por ejemplo, durante comandos Drush sin contexto de dominio), no se aplican sobrescrituras y se utiliza la configuración base.
Negociación temprana para middlewares
Si los middlewares de terceros necesitan sobrescrituras de
domain_config antes de que se dispare el evento kernel request,
instale el módulo Domain Early Negotiation
(domain_early_negotiation) del proyecto
Domain Extras.
Consulte la
documentación de Domain
para más detalles.
Cache¶
El servicio de sobrescritura proporciona un sufijo de cache basado en el ID del dominio actual. Esto garantiza que los objetos de configuración almacenados en cache para un dominio no se sirvan a otro.
Los metadatos de cache incluyen el cache context domain, por lo que
el contenido renderizado que depende de configuración específica de
dominio varía correctamente.
Guardado de las sobrescrituras¶
Al guardar una sobrescritura,
DomainConfigOverrideEditable::save() solo conserva las claves cuyo
valor realmente cambia con respecto a la base. El resto se ignora:
la sobrescritura solo contiene las diferencias.
Funciona igual para las dos formas de escribir en la config:
ConfigFormBase, que llama aset()clave por clave,ConfigEntityStorage::doSave(), que llama asetData()con toda la config de una vez.
El resultado almacenado es el mismo: una sobrescritura mínima.
Dos consecuencias útiles a tener en cuenta:
- devolver una clave a su valor de base la retira de la sobrescritura, salvo si esa clave está declarada como fijada (ver más abajo);
- cambiar otra clave en una config ya sobrescrita (por ejemplo cambiar la región de un bloque cuyo label es lo único sobrescrito) no toca la sobrescritura existente: la nueva diferencia simplemente se añade.
Claves fijadas¶
Retirar una clave porque es idéntica a la base hace perder la diferencia entre «este dominio sigue al sitio» y «este dominio mantiene este valor». Solo la segunda tiene que sobrevivir a un cambio posterior de la base: un dominio al que se le ha dado el tema por defecto del sitio debería conservar ese tema aunque ese valor por defecto cambie.
Las claves listadas en domain_config.settings:pinned_keys, o
añadidas por hook_domain_config_pinned_keys_alter(), quedan exentas
del cálculo de diferencias. Se escriben en la sobrescritura cada vez
que el objeto de configuración se guarda para un dominio, difiera o no
su valor del de la base. Todo lo demás sigue siendo mínimo.
La lista se edita en el formulario de ajustes de Domain Config UI, un objeto de configuración por línea:
system.theme: default, admin
Dos consecuencias a tener en cuenta. Guardar el objeto para un dominio que no tenía ninguna sobrescritura crea una con las claves fijadas, así que fije solo lo que merezca la pena. Y eliminar la sobrescritura de un dominio supone eliminar también la declaración; si no, el siguiente guardado vuelve a escribir las claves fijadas.
La fijación usa una lista con nombre en lugar de un comportamiento por
defecto porque save() no distingue las dos formas de escribir: quien
usa set() clave por clave podría fijar sin riesgo todo lo que toca,
pero setData() entrega el objeto entero, y «fijarlo todo» ahí
almacenaría una copia completa de la configuración para cada dominio,
justo la duplicación que la sobrescritura mínima evita.
A la inversa, la lectura sin sobrescritura
(ConfigEntityStorage::loadMultipleOverrideFree()) es un problema
distinto y no se trata aquí. Ver
#3587744 y el
submódulo domain_config_entity_ui previsto en
domain_extras.
Limitación conocida: acortar una lista¶
Una sobrescritura por dominio no puede acortar una sequence: los
elementos presentes en la base más allá de la longitud de la
sobrescritura siguen visibles. Esta limitación viene del core de
Drupal, no de domain_config.
Ejemplo. La base tiene allowed_tags: ['a', 'em', 'strong', 'p'].
La sobrescritura la reemplaza por ['a', 'em', 'strong'] — se
quiere quitar 'p'. En la lectura, el core fusiona mediante
NestedArray::mergeDeepArray([$base, $override], TRUE). La fusión
recorre los arreglos clave por clave, por lo que 'p' (en el
índice 3) permanece, y el visitante sigue viendo los cuatro
elementos.
El formato de las sobrescrituras no sabe expresar «ignora el índice
N de la base». Por eso domain_config no puede corregir este
comportamiento sin alejarse de cómo funcionan las demás
sobrescrituras de Drupal (settings.php, sobrescrituras de módulos,
etc.).
Según el caso, hay varias soluciones:
- si controlas el esquema, sustituir la
sequencepor unmappingasociativo: las sobrescrituras funcionan correctamente sobre maps asociativos; - sobrescribir más bien la clave padre y escribir ahí la lista completa deseada mediante código;
- modificar directamente la configuración de base.
Eventos del ciclo de vida de configuración¶
Domain Config 3.x gestiona adecuadamente los eventos del ciclo de vida de la configuración para mantener las sobrescrituras de dominio sincronizadas con la configuración base:
| Evento | Comportamiento |
|---|---|
| Config save | Para cada dominio, si existe una sobrescritura de dominio para la configuración guardada, se filtra para eliminar los valores idénticos a la nueva configuración base (conservando solo las sobrescrituras reales). |
| Config delete | Si se elimina la configuración base, la sobrescritura de dominio correspondiente se elimina de todas las colecciones de dominio. |
| Config rename | Si se renombra la configuración base, la sobrescritura se renombra en todas las colecciones de dominio para coincidir. |
Exportación e importación de configuración¶
Como las sobrescrituras viven en colecciones de Drupal, se integran con el sistema de exportación/importación de configuración:
Estructura del directorio de exportación:
El FileStorage de Drupal convierte los puntos en los nombres de
colección en separadores de directorio. La colección
domain.one_example_com se convierte en el directorio
domain/one_example_com/:
config/sync/
system.site.yml # Configuración base
domain/
one_example_com/
system.site.yml # Sobrescritura por dominio
two_example_com/
system.site.yml
Los módulos también pueden incluir sobrescrituras de dominio por
defecto usando la misma convención en su directorio
config/install/:
mymodule/config/install/
domain/
one_example_com/
system.site.yml
two_example_com/
system.site.yml
Cuando se crea una nueva entidad de dominio,
installDomainOverrides() llama a
ConfigInstallerInterface::installCollectionDefaultConfig() de Drupal
para instalar los valores por defecto proporcionados por los módulos
para la colección de ese dominio.
Cuando domain_config_language está instalado, este mismo esquema se
extiende con un subdirectorio language/{langcode}/ bajo cada carpeta
de dominio — véase la
documentación de Domain Config Language.
Domain Config UI¶
El módulo opcional Domain Config UI proporciona una interfaz de usuario para gestionar las sobrescrituras por dominio directamente desde los formularios de configuración existentes.
Consulte la documentación de Domain Config UI para más detalles sobre:
- Activar/desactivar sobrescrituras por configuración y por dominio.
- El enlace de acción en línea en los formularios de administración.
- Configuraciones no permitidas.
- Control programático mediante alter hooks.
Migración de 2.x a 3.x¶
La migración 2.x → 3.x la lleva domain_config_language porque
todo sitio 2.x con sobrescrituras por dominio tenía también el módulo
language activado, y el formato de almacenamiento heredado era el
mismo independientemente de si había sobrescrituras por idioma o no.
domain_config_update_10002() instala automáticamente
domain_config_language durante drush updatedb cuando language
está activado, y la migración se ejecuta desde
domain_config_language_install().
Véase la documentación de Domain Config Language para los pasos completos de la migración y las notas de retroceso.
Servicios¶
| Servicio | Clase | Función |
|---|---|---|
domain.config_factory_override |
DomainConfigFactoryOverride |
Sobrescrituras de configuración por dominio (prioridad -253) |
domain_config.library.discovery.collector |
DomainConfigLibraryDiscoveryCollector |
Decora el recolector de caché del descubrimiento de librerías para que las definiciones se almacenen en caché por dominio |
DomainConfigServiceProvider apunta ese decorador al servicio con el que el
núcleo en ejecución construye la información de librerías:
library.discovery.collector hasta Drupal 11.0, y library.discovery a partir
de Drupal 11.1, donde el núcleo trasladó allí el recolector de caché.