Déboguer WordPress avec un simple var_dump, on est tous passés par là… et on a tous fini par se retrouver noyés dans un mur de texte incompréhensible au moindre problème un peu complexe. Heureusement, la combinaison Xdebug 3, PhpStorm et Docker a clairement changé la donne : on pose un breakpoint, on inspecte les variables en temps réel, et on comprend enfin ce qui se passe vraiment dans les entrailles de WordPress. Dans cet article, on va mettre en place cette stack de débogage de A à Z, et je vous promets qu’une fois que vous y aurez goûté, il sera difficile de faire marche arrière.
Pourquoi Xdebug 3 + PhpStorm + Docker change tout pour déboguer WordPress
Si vous avez déjà passé deux heures à traquer un bug dans WordPress avec des var_dump() éparpillés dans le code, vous savez exactement de quoi je parle. Ça fonctionne… jusqu’à un certain point. Mais sur des projets complexes, cette approche montre très vite ses limites. C’est là que la combinaison Xdebug 3 + PhpStorm + Docker entre en jeu — et croyez-moi, ça change vraiment la donne.
Le débogage WordPress old school : ses limites
On a tous commencé pareil : activer WP_DEBUG dans le wp-config.php, balancer quelques var_dump() ou error_log() à droite à gauche, puis recharger la page en croisant les doigts. Pour un petit bug isolé, ça peut suffire. Mais dès qu’on attaque un projet avec un thème sur-mesure, une dizaine de plugins, des hooks imbriqués et des requêtes complexes en base de données… c’est un cauchemar.
Le problème principal : ces méthodes sont statiques et aveugles. On injecte du code, on recharge, on lit les logs, on recommence. On ne voit pas l’état de l’application au moment précis où le bug survient. Impossible de suivre le fil d’exécution pas à pas, d’inspecter une variable profondément imbriquée dans un objet, ou de comprendre pourquoi un hook ne se déclenche pas au bon moment. Et puis, avouons-le : retrouver tous ses var_dump() oubliés avant de mettre en production, c’est un sport à part entière.
Ce que Xdebug 3 apporte concrètement
Xdebug existe depuis longtemps, mais la version 3.x (sortie fin 2020 et toujours largement adoptée en 2026) a apporté une refonte majeure : configuration simplifiée, performances bien améliorées, et une intégration plus fluide avec les IDE modernes.
Concrètement, Xdebug 3 vous permet de :
- Poser des breakpoints directement dans votre code PHP, sans toucher au code source
- Avancer pas à pas dans l’exécution (step into, step over, step out)
- Inspecter toutes les variables en temps réel, y compris les objets WordPress les plus complexes
- Analyser la pile d’appels (call stack) pour comprendre comment on en est arrivé là
- Profiler les performances de vos fonctions pour identifier les goulots d’étranglement
La métaphore qui me semble la plus juste : Xdebug, c’est passer de la lampe torche au scanner médical pour inspecter son code. Avant, on tâtonnait dans l’obscurité. Maintenant, on voit tout, en temps réel, avec une précision chirurgicale.
Couplé à PhpStorm (l’IDE de JetBrains, disponible aux alentours de 24,90 €/mois ou ~200 €/an), l’expérience est vraiment fluide : l’intégration native avec Xdebug est excellente, les breakpoints se posent d’un clic, et l’inspecteur de variables est particulièrement bien pensé pour les structures de données WordPress (les WP_Query, WP_Post et autres objets tentaculaires).
Pourquoi Docker est la brique indispensable en 2026
Bonne question. On pourrait très bien utiliser Xdebug avec MAMP, WAMP ou Local by Flywheel. Et franchement, pour des projets simples, ça marche. Mais Docker apporte quelque chose que ces solutions ne peuvent pas offrir : la reproductibilité exacte de l’environnement de production.
En 2026, les projets WordPress sérieux tournent presque tous dans des environnements conteneurisés. Ça veut dire que le bug que vous debuggez en local, vous pouvez être certain qu’il se reproduira dans les mêmes conditions qu’en production — même version de PHP, même configuration serveur, mêmes extensions activées. Fini le classique « ça marche sur ma machine mais pas en prod ».
Et puis, Docker facilite grandement le travail en équipe : tout le monde partage le même docker-compose.yml, et la configuration Xdebug fait partie du projet. C’est d’ailleurs devenu quasi standard dans les agences WordPress sérieuses. Pas étonnant : le gain de temps sur le débogage est considérable, et l’onboarding d’un nouveau développeur se réduit à un simple docker compose up.
Configurer l’environnement Docker pour WordPress avec Xdebug 3
On attaque maintenant le cœur du sujet : mettre en place un environnement Docker propre, reproductible, et prêt pour le débogage avec Xdebug 3. Rien de magique ici — juste une configuration solide, quelques pièges à éviter, et des fichiers bien commentés.
Structurer son docker-compose.yml pour WordPress
La base, c’est un docker-compose.yml qui orchestre au minimum trois services : WordPress (avec notre image PHP custom), MySQL 8.x, et optionnellement phpMyAdmin pour gérer la base sans se prendre la tête.
# docker-compose.yml
version: "3.9"
services:
wordpress:
build:
context: .
dockerfile: Dockerfile # Notre image custom avec Xdebug 3
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: wp_password
WORDPRESS_DB_NAME: wp_db
volumes:
- ./wp-content:/var/www/html/wp-content # On monte uniquement wp-content
- ./xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
depends_on:
- mysql
# IMPORTANT sur Linux : host.docker.internal n'est pas résolu automatiquement
# Il faut ajouter cette entrée manuellement (inutile sur Mac/Windows)
extra_hosts:
- "host.docker.internal:host-gateway"
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: wp_db
MYSQL_USER: wp_user
MYSQL_PASSWORD: wp_password
volumes:
- mysql_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin:latest
ports:
- "8081:80"
environment:
PMA_HOST: mysql
depends_on:
- mysql
volumes:
mysql_data:
Notez bien le extra_hosts sur le service WordPress : c’est le piège classique sur Linux, on y revient juste après.
Créer le Dockerfile PHP custom avec Xdebug 3
L’image officielle wordpress:php8.3-apache ne vient pas avec Xdebug. On doit donc construire notre propre image par-dessus. C’est plus simple qu’il n’y paraît :
# Dockerfile
# On part de l'image officielle WordPress avec PHP 8.3
FROM wordpress:php8.3-apache
# Installation de Xdebug 3 via PECL
# pecl install xdebug installe la dernière version stable (3.x en 2026)
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
# Le fichier xdebug.ini est monté via un volume dans docker-compose.yml
# Pas besoin de le copier ici — ça facilite les modifications sans rebuild
C’est tout. Vraiment. On garde le Dockerfile minimal et on gère la configuration via un volume monté. Ainsi, modifier xdebug.ini ne nécessite pas de reconstruire l’image à chaque fois — un simple docker compose restart wordpress suffit.
Paramétrer xdebug.ini : les options clés en 2026
C’est ici que beaucoup de gens se perdent. Voici un fichier xdebug.ini complet et commenté :
; xdebug.ini[xdebug]
; Mode débogage — « debug » active les breakpoints et l’inspection pas-à-pas ; Autres modes possibles : coverage, profile, trace (ou combinaisons : « debug,coverage ») xdebug.mode=debug; Déclenche automatiquement une session de débogage à chaque requête ; Alternative : « trigger » (plus léger en prod, mais on est en dev ici) xdebug.start_with_request=yes; L’adresse de votre machine hôte — là où PhpStorm écoute ; Sur Mac et Windows, host.docker.internal fonctionne nativement ; Sur Linux, extra_hosts dans docker-compose.yml est OBLIGATOIRE (voir plus haut) xdebug.client_host=host.docker.internal; ATTENTION : Xdebug 3 utilise le port 9003 par défaut ; Xdebug 2 utilisait le port 9000 — c’est une source d’erreur fréquente si vous migrez xdebug.client_port=9003; Identifiant de session — doit correspondre à la config PhpStorm xdebug.idekey=PHPSTORM; Fichier de log utile pour diagnostiquer les problèmes de connexion xdebug.log=/tmp/xdebug.log; Limite la profondeur d’inspection des variables imbriquées xdebug.max_nesting_level=512
Le point critique à retenir : le changement de port 9000 → 9003 entre Xdebug 2 et Xdebug 3. Si vous avez un ancien projet ou que vous suivez un tutoriel daté, c’est souvent là que ça coince. PhpStorm écoute sur 9003 par défaut depuis un moment déjà — vérifiez simplement que les deux correspondent.
Et sur Linux, encore une fois : sans extra_hosts: - "host.docker.internal:host-gateway" dans votre docker-compose.yml, le container ne saura pas résoudre host.docker.internal et Xdebug ne pourra jamais joindre PhpStorm. Sur Mac et Windows avec Docker Desktop, ce n’est pas nécessaire — Docker gère ça automatiquement.
Vérifier que Xdebug est bien actif
Une fois l’environnement lancé avec docker compose up -d --build, on vérifie que Xdebug est bien chargé. Deux méthodes :
Via la ligne de commande :
# Exécuter php -m dans le container WordPress
docker compose exec wordpress php -m | grep xdebug
# Résultat attendu : xdebug
Via phpinfo() :
Créez temporairement un fichier info.php à la racine de WordPress :
<?php phpinfo(); ?>
Accédez à http://localhost:8080/info.php et cherchez la section « xdebug ». Vous devriez voir le mode actif, la version (3.x), et tous les paramètres configurés.
Et surtout, pensez à supprimer ce fichier une fois la vérification faite. Laisser un phpinfo() accessible, même en local, c’est une mauvaise habitude à ne pas prendre.
Si Xdebug n’apparaît pas, consultez /tmp/xdebug.log dans le container : il contient généralement un message clair sur ce qui bloque.
docker compose exec wordpress cat /tmp/xdebug.log
Connecter PhpStorm à Docker et poser ses premiers breakpoints
On a notre environnement Docker qui tourne, Xdebug 3 est installé et configuré… mais il manque encore la pièce centrale : dire à PhpStorm comment communiquer avec le conteneur. C’est souvent là que les gens bloquent. La bonne nouvelle, c’est qu’une fois la configuration en place, tout devient vraiment magique.
Configurer le serveur PHP et le path mapping dans PhpStorm
Ouvrez Settings (ou Preferences sur macOS) puis naviguez vers PHP > Servers. Cliquez sur le + pour créer un nouveau serveur. Le nom que vous donnez ici est critique : il doit correspondre exactement à la valeur de xdebug.idekey (ou à la variable PHP_IDE_CONFIG définie dans votre docker-compose.yml). En général, on utilise simplement wordpress ou docker.
Remplissez ensuite :
- Host :
localhost - Port :
8080ou8000selon ce que vous avez mappé dans votredocker-compose.yml - Debugger : Xdebug
Maintenant, cochez Use path mappings — c’est l’étape que beaucoup oublient. PhpStorm doit savoir faire le lien entre les fichiers sur votre machine et leur emplacement dans le conteneur. Mappez le dossier racine de votre projet local vers /var/www/html (ou le chemin défini dans votre Dockerfile). Sans ça, PhpStorm reçoit bien les signaux de Xdebug, mais il ne trouve pas les fichiers correspondants. Le résultat : une session de debug qui s’ouvre dans le vide, frustrant !
Une fois sauvegardé, activez l’écoute dans PhpStorm via le bouton Start Listening for PHP Debug Connections (l’icône téléphone en haut à droite de l’IDE, ou le raccourci Alt+Shift+D sur Windows/Linux). Le bouton passe en rouge : PhpStorm attend désormais les connexions entrantes sur le port 9003.
Lancer une session de debug et inspecter les variables WordPress
Pour déclencher une session depuis le navigateur, le plus pratique reste l’extension Xdebug Helper (disponible sur Chrome et Firefox, totalement gratuite). Une fois installée, cliquez sur l’icône dans votre barre d’outils et activez le mode Debug. Elle ajoute automatiquement le cookie XDEBUG_SESSION à vos requêtes — pas besoin de bricoler les URLs à la main.
Posez maintenant un breakpoint : ouvrez par exemple wp-includes/functions.php ou le fichier principal de votre plugin custom, et cliquez dans la marge gauche à côté du numéro de ligne. Un point rouge apparaît. Rechargez la page dans le navigateur.
Si tout est bien configuré, PhpStorm passe au premier plan et la fenêtre Debug s’ouvre. Voilà ce que vous pouvez inspecter :
- Call Stack (pile d’appels) : vous voyez exactement comment WordPress est arrivé jusqu’à cette ligne, fonction par fonction. Très utile pour comprendre l’ordre d’exécution des hooks.
- Variables :
$wpdb,$post,$wp_query, vos variables locales… tout est là, avec leur valeur réelle au moment de l’exécution. Plus besoin devar_dumpsuivi d’undie(). - Watches / Evaluate Expression : vous pouvez évaluer n’importe quelle expression PHP en live, directement dans le contexte d’exécution. Tester
$wpdb->last_queryouget_queried_object()sans modifier une seule ligne de code, c’est un gain de temps énorme.
Soyons honnêtes : la première fois, on passe facilement 30 à 45 minutes à chercher pourquoi ça ne se connecte pas. Path mapping mal configuré, port bloqué, IDE key qui ne correspond pas… Les erreurs classiques sont nombreuses. Mais une fois que ça fonctionne — et ça finit toujours par fonctionner — vous ne reviendrez plus en arrière. Déboguer WordPress avec des vraies breakpoints, c’est un autre niveau.
Cas pratiques : déboguer des situations WordPress courantes avec Xdebug
Bon, maintenant qu’on a tout configuré — Docker, Xdebug 3 et PhpStorm — il serait dommage de s’arrêter là. La vraie valeur d’un debugger, c’est quand on l’applique à des situations concrètes. Voici trois cas que je rencontre régulièrement dans mes projets WordPress, et qui montrent bien toute la puissance de cette stack.
Tracer l’exécution d’un hook ou d’un filtre WordPress
C’est probablement le cas d’usage que j’utilise le plus souvent. Quand un filtre comme the_content ou un action hook comme save_post produit un comportement inattendu, var_dump ne suffit plus — surtout quand plusieurs plugins s’accrochent au même hook.
La méthode : placez un breakpoint directement dans votre fonction accrochée au hook. Par exemple, pour déboguer the_content :
add_filter('the_content', 'mon_filtre_contenu');
function mon_filtre_contenu($content) {
// Placez votre breakpoint ici
return $content;
}
En suspendant l’exécution à cet endroit, PhpStorm vous affiche le $content transmis, mais aussi — et c’est là que ça devient intéressant — la call stack complète. On voit exactement dans quel ordre les hooks ont été exécutés avant d’arriver ici. J’ai résolu des conflits de plugins en quelques minutes grâce à ça, alors qu’auparavant j’aurais passé une heure à ajouter des error_log() un peu partout.
Pour save_post, même logique : inspectez l’objet $post transmis, vérifiez ses propriétés, comprenez pourquoi les données sauvegardées ne correspondent pas à ce que vous attendez.
Déboguer une requête WP_Query ou $wpdb lente
Les requêtes SQL sont souvent à l’origine de performances dégradées ou de résultats inattendus. Xdebug permet ici d’aller vraiment au fond du problème.
Pour une WP_Query, placez un breakpoint après l’instanciation :
$query = new WP_Query($args);
// Breakpoint ici : inspectez $query->request pour voir le SQL généré
La propriété $query->request contient la requête SQL finale — celle qui a vraiment été envoyée à la base de données. On peut aussi inspecter $query->posts pour comprendre pourquoi des résultats inattendus remontent.
Pour $wpdb, c’est encore plus direct. Après un $wpdb->get_results(), la propriété $wpdb->last_query contient la dernière requête exécutée. J’ai eu un cas récemment où une meta query générait un JOIN monstrueux à cause d’un tableau $args mal construit — sans Xdebug, j’aurais galéré longtemps. En inspectant $wpdb->last_query dans PhpStorm, le problème était évident en 30 secondes.
Profiler ses performances avec Xdebug 3 et QCacheGrind
Le profiling, c’est un mode différent du debug classique. On ne place pas de breakpoints : Xdebug enregistre tous les appels de fonctions avec leur temps d’exécution dans un fichier cachegrind. Pour l’activer, on change le mode dans le xdebug.ini :
xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=cachegrind.out.%p
Attention point important : le mode profile et le mode debug ne se combinent pas bien simultanément. L’impact sur les performances est tel que les résultats deviennent peu fiables. Activez-les séparément selon votre besoin du moment — c’est d’ailleurs là où les variables d’environnement Docker prennent tout leur sens (j’y reviens juste après).
Une fois le fichier cachegrind généré, ouvrez-le dans QCacheGrind (gratuit, disponible sur Windows, Mac et Linux). L’interface vous présente un arbre d’appels avec les fonctions les plus coûteuses en tête. On peut ainsi identifier si c’est une requête, un hook particulier ou un plugin tiers qui plombe les performances.
Et pour aller encore plus loin dans l’analyse des appels, Xdebug 3 propose aussi le mode trace (xdebug.mode=trace), qui logue absolument tous les appels de fonctions dans un fichier texte. C’est très verbeux, mais utile pour comprendre un flux d’exécution complexe.
Une règle absolue pour conclure : ne laissez jamais Xdebug actif en production. L’impact sur les performances est majeur, même sans session de debug active. La bonne pratique avec Docker, c’est d’utiliser des variables d’environnement pour contrôler l’activation :
# docker-compose.yml
environment:
XDEBUG_MODE: ${XDEBUG_MODE:-off}
Ainsi, en local on définit XDEBUG_MODE=debug dans son .env, et en production la valeur par défaut est off. Simple, efficace, et ça évite les mauvaises surprises.
