Un réseau de neuf sites vitrines pour une franchise de salles de sport a mis en évidence, avec une extension de réservation de cours collectifs à peine terminée, un lot de bugs qui n’apparaissaient jamais en installation simple. Chaque site du réseau avait ses propres cours, mais un tableau de bord centralisé, réservé au super administrateur, devait agréger les réservations de tous les sites. Voici la checklist qui s’est progressivement construite en corrigeant ces bugs un par un.
1. Vérifier le paramètre d’activation réseau
Le hook register_activation_hook reçoit un second paramètre, $network_wide, ignoré par la majorité des tutoriels d’introduction. Sans le traiter, une activation réseau ne crée les tables et options nécessaires que pour le site sur lequel l’administrateur se trouvait au moment du clic.
function fitness_activer( $network_wide ) {
if ( is_multisite() && $network_wide ) {
foreach ( get_sites( array( 'fields' => 'ids' ) ) as $site_id ) {
switch_to_blog( $site_id );
fitness_creer_tables_site();
restore_current_blog();
}
} else {
fitness_creer_tables_site();
}
}
register_activation_hook( __FILE__, 'fitness_activer' );
2. Gérer l’ajout d’un nouveau site après coup
Un réseau grandit rarement une seule fois : un dixième site peut être créé des mois après l’activation réseau initiale de l’extension. Le hook wp_initialize_site permet d’exécuter la même routine d’initialisation pour tout nouveau site rejoignant le réseau.
add_action( 'wp_initialize_site', function ( $new_site ) {
switch_to_blog( $new_site->blog_id );
fitness_creer_tables_site();
restore_current_blog();
}, 10, 1 );
3. Choisir entre options de site et options de réseau

Une donnée propre à chaque salle de sport (ses horaires, ses coachs) relève de get_option / update_option, propres à chaque site. Une donnée partagée par tout le réseau (une clé d’API commune, un tarif de licence global) relève de get_site_option / update_site_option, stockées une seule fois pour l’ensemble du réseau.
- Confondre les deux est l’erreur la plus fréquente : une clé d’API stockée avec
update_optiondevrait être ressaisie sur chacun des neuf sites, alors qu’elle est identique partout get_site_optionretombe automatiquement sur les valeurs du réseau principal si aucune valeur spécifique n’est enregistrée- Les tables personnalisées, elles, doivent généralement être dupliquées par site (avec le préfixe propre à chaque blog) sauf choix architectural explicite d’une table réseau unique
4. Parcourir les sites avec switch_to_blog correctement
Le tableau de bord centralisé de réservations devait interroger, tour à tour, chacun des neuf sites. switch_to_blog() change le contexte de $wpdb et de la plupart des fonctions de contenu, mais pas systématiquement tout le reste de l’environnement.
foreach ( get_sites( array( 'fields' => 'ids' ) ) as $site_id ) {
switch_to_blog( $site_id );
$reservations = get_posts( array(
'post_type' => 'reservation',
'posts_per_page' => -1,
) );
fitness_agreger_reservations( $site_id, $reservations );
restore_current_blog();
}
Toujours appeler restore_current_blog() après chaque switch_to_blog(), y compris en cas de sortie anticipée d’une fonction (via un return précoce en cas d’erreur) : un oubli laisse le contexte de requête basculé sur le mauvais site pour tout le reste de l’exécution de la page.
5. Distinguer capacité globale et capacité par site
Un utilisateur peut être administrateur d’un site du réseau sans être super administrateur du réseau lui-même. Vérifier uniquement current_user_can( 'manage_options' ) pour autoriser l’accès au tableau de bord centralisé aurait exposé les données des neuf salles à n’importe quel administrateur local d’un seul site.
if ( ! is_super_admin() ) {
wp_die( 'Accès réservé au réseau.' );
}
is_super_admin() reste la fonction correcte pour ce cas précis, distincte de toute vérification de capacité classique, elle-même toujours relative au site courant.
Les points restants de la checklist
- Tester la désactivation et la désinstallation en contexte réseau, pas uniquement l’activation
- Vérifier qu’aucun chemin de fichier n’est codé en dur avec l’hypothèse d’un unique répertoire d’uploads (chaque site multisite a son propre sous-répertoire)
- S’assurer qu’un cache d’objets persistant partagé entre sites ne mélange pas les clés de cache d’un site à l’autre (préfixer les clés avec l’identifiant du site si nécessaire)
- Documenter clairement, dans le fichier readme, si l’extension nécessite une activation réseau ou site par site
En résumé
Une extension réellement compatible multisite ne se contente pas de « ne pas planter » sur un réseau : elle distingue consciemment ce qui relève du réseau et ce qui relève de chaque site, gère l’ajout tardif de nouveaux sites, et sépare rigoureusement les capacités globales des capacités locales. Cette checklist, née de bugs bien réels sur ce projet de salles de sport, reste celle que je reprends systématiquement avant toute publication destinée à un client multisite.