# Architecture d’une extension pour un réseau de 500 sites : un cœur commun

> Concevoir un paquet central partagé et des extensions spécifiques par filiale pour un grand groupe multisite sans dupliquer le code d'une instance à l'autre.

- Auteur : Clément Hadrot
- Publié le : 2024-03-12
- Mis à jour le : 2024-03-12
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/architecture-extension-reseau-500-sites-coeur-commun/

## L’essentiel

- Un cœur commun versionné, jamais copié-collé d'un site à l'autre
- Les extensions spécifiques ne redéfinissent jamais une fonction du cœur
- Chaque filiale garde un canal de mise à jour indépendant

500 instances WordPress distinctes, chacune gérée par une filiale différente d'un même groupe, avec des besoins communs (référencement des points de vente, formulaire de contact standardisé, bandeau de conformité RGPD) et des besoins spécifiques propres à chaque marché local. C'est le paysage sur lequel il a fallu concevoir une architecture d'extension qui ne repose ni sur un réseau multisite unique — politiquement impossible entre filiales autonomes — ni sur cinq cents copies indépendantes du même code, invivable à maintenir dans la durée.

La solution retenue s'articule autour d'un principe simple à énoncer et exigeant à tenir : un cœur commun, versionné et distribué comme un paquet Composer privé, complété par des extensions spécifiques par filiale qui ne redéfinissent jamais ce que fait le cœur, seulement ce qu'il ne fait pas.

## Le cœur commun : un paquet, pas un thème parent

Le cœur applicatif est distribué comme une bibliothèque PHP autonome, indépendante de tout thème, hébergée sur un dépôt privé accessible via Composer et un serveur Satis interne. Il regroupe les briques réellement partagées par les 500 sites : les types de contenu personnalisés communs, les hooks de conformité RGPD, l'intégration au référentiel central des points de vente. Aucune filiale ne modifie ce code directement ; toute évolution du cœur passe par une demande centralisée, testée sur un environnement de préproduction commun avant diffusion.

```
{
  "require": {
    "monagence/core-reseau": "^4.2",
    "php": ">=8.1"
  },
  "repositories": [
    { "type": "composer", "url": "https://satis.interne.monagence.fr" }
  ]
}
```

## L'arborescence type d'un site de filiale

> L'essentiel à retenir : Un cœur commun versionné, jamais copié-collé d'un site à l'autre ; Les extensions spécifiques ne redéfinissent jamais une fonction du cœur ; Chaque filiale garde un canal de mise à jour indépendant

Chaque site de filiale reçoit une arborescence standardisée, générée par un script de scaffolding interne, qui distingue clairement ce qui vient du cœur, ce qui est spécifique, et ce qui ne doit jamais être modifié à la main :

```
wp-content/
├── plugins/
│   ├── monagence-core/          (installé via Composer, jamais modifié à la main)
│   └── filiale-normandie/       (extension spécifique à cette filiale)
│       ├── filiale-normandie.php
│       └── inc/
│           └── class-specificites-locales.php
└── mu-plugins/
    └── loader-core.php          (charge le cœur avant toute extension spécifique)
```

Le fichier `loader-core.php`, placé en *must-use plugin*, garantit que le cœur se charge avant toute extension spécifique, quel que soit l'ordre alphabétique naturel des dossiers dans `plugins/`, qui ne peut pas être fiable à l'échelle de cinq cents installations gérées par des équipes différentes.

## La règle qui protège le cœur des extensions locales

La contrainte la plus difficile à faire respecter n'est pas technique mais organisationnelle : empêcher qu'une extension spécifique à une filiale redéfinisse une fonction ou un hook du cœur pour répondre à un besoin ponctuel. Trois garde-fous ont été mis en place :

- Toutes les fonctions du cœur sont préfixées et namespacées, rendant impossible une redéfinition accidentelle par un développeur local peu expérimenté.
- Le cœur expose des points d'extension explicites via des hooks documentés (`monagence_core_avant_export_point_vente`, par exemple), plutôt que de laisser les filiales modifier son comportement par surcharge.
- Une revue de code centralisée est obligatoire avant toute mise en production d'une extension spécifique qui touche à un hook exposé par le cœur.

## Le canal de mise à jour, filiale par filiale

Toutes les filiales ne peuvent pas monter de version du cœur au même rythme : certaines ont des contraintes de campagne commerciale qui interdisent tout changement pendant plusieurs semaines. Le mécanisme de diffusion s'appuie donc sur des contraintes de version Composer par environnement (`^4.2` pour les filiales stables, une branche de développement pour les pilotes), avec un serveur de mise à jour interne qui respecte ces contraintes plutôt que de pousser une version unique à l'ensemble du parc en même temps.

> La leçon organisationnelle la plus utile de ce projet : une architecture technique correcte ne suffit pas si aucune règle claire n'empêche une filiale pressée de contourner le cœur pour livrer plus vite. Le garde-fou humain compte autant que le garde-fou technique.

## Ce qu'on retient

Un cœur commun distribué en paquet Composer, chargé en must-use plugin, complété par des extensions spécifiques strictement cantonnées à leurs propres hooks d'extension, permet de faire cohabiter cinq cents sites autonomes sans dupliquer le code métier partagé. La discipline de revue de code compte autant que l'architecture elle-même : sans elle, le cœur commun finit inévitablement par se fragmenter en cinq cents variantes légèrement différentes, ce que cette organisation vise précisément à éviter.
