PHPUnit et PHPCS couvrent deux besoins différents : vérifier que le code fait ce qu’il doit faire, et vérifier qu’il respecte un style donné. Aucun des deux ne détecte qu’une fonction passe un tableau là où une chaîne est attendue, ou qu’une variable peut être null au moment où on appelle une méthode dessus. C’est le rôle de l’analyse statique, et PHPStan s’est imposé comme la référence dans l’écosystème PHP pour ce type de vérification, sans jamais exécuter le code.
Sur un projet WordPress, PHPStan se heurte cependant à un problème immédiat : il ne connaît ni les fonctions du cœur, ni les classes comme WP_Post ou WP_Query, ni les types de retour souvent incertains d’API comme get_option(). L’extension szepeviktor/phpstan-wordpress comble ce vide. Voici comment la mettre en place sur un projet existant sans se noyer sous les faux positifs.
Installer PHPStan et l’extension WordPress
composer require --dev phpstan/phpstan
composer require --dev szepeviktor/phpstan-wordpress
L’extension fournit des stubs, des définitions de types pour les fonctions et classes du cœur WordPress, ainsi que la configuration nécessaire pour que PHPStan sache où trouver l’installation de WordPress lors de l’analyse.
Configurer phpstan.neon
La configuration se fait dans un fichier phpstan.neon à la racine du projet :
parameters:
level: 5
paths:
- mon-plugin.php
- includes
excludePaths:
- vendor/*
- tests/*
bootstrapFiles:
- vendor/szepeviktor/phpstan-wordpress/bootstrap.php
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
Le fichier de bootstrap fourni par l’extension déclare les constantes WordPress courantes (ABSPATH, WPINC…) et charge les stubs qui décrivent les fonctions du cœur, ce qui évite des centaines de faux positifs du type « fonction inconnue : get_post() ».

Choisir le bon niveau pour démarrer
PHPStan propose des niveaux de rigueur de 0 à 9 (le niveau maximal). Sur un projet neuf, viser directement un niveau élevé a du sens. Sur un projet existant de plusieurs années, lancer PHPStan au niveau 9 dès le premier jour produit en général des milliers d’erreurs, la plupart sans rapport avec de vrais bugs, ce qui décourage plus vite qu’autre chose.
Notre approche sur les projets clients existants : démarrer au niveau 0 ou 1 pour vérifier l’absence d’erreurs grossières (fonctions inexistantes, nombre d’arguments incorrect), puis monter progressivement, en s’arrêtant généralement au niveau 5 ou 6 dans un premier temps. Ce palier détecte déjà la majorité des vrais bugs : appels de méthode sur une valeur potentiellement null, types de retour incohérents, variables non définies dans certains chemins d’exécution.
vendor/bin/phpstan analyse --level=5
Un exemple concret de bug détecté
Sur un plugin client, PHPStan au niveau 5 a signalé ce code, en place depuis plus d’un an :
function mon_plugin_get_titre_produit( $product_id ) {
$post = get_post( $product_id );
return $post->post_title;
}
PHPStan signale que get_post() peut retourner null si l’ID ne correspond à aucun article, et qu’appeler ->post_title sur null provoquerait une erreur fatale en PHP 8. Ce cas ne s’était encore jamais produit en production, mais uniquement parce que la fonction n’avait jamais été appelée avec un ID invalide. La correction est directe :
function mon_plugin_get_titre_produit( $product_id ) {
$post = get_post( $product_id );
if ( ! $post instanceof WP_Post ) {
return '';
}
return $post->post_title;
}
C’est exactement le type de bug latent que ni PHPUnit ni PHPCS ne détectent : le code respecte le style, et aucun test existant ne couvrait le cas d’un ID invalide.
Ignorer certaines erreurs sans les faire disparaître
Certaines erreurs remontées par PHPStan concernent du code que l’on sait correct, mais que l’outil ne peut pas prouver statiquement, par exemple à cause d’une action WordPress qui modifie dynamiquement un tableau. Plutôt que de baisser le niveau global, PHPStan permet d’ignorer des erreurs précises :
parameters:
ignoreErrors:
- '#Call to an undefined method WC_Product::get_custom_champ\(\)#'
Cette approche garde une trace explicite, dans le fichier de configuration versionné, de chaque exception accordée, plutôt que de la traiter silencieusement.
Intégrer PHPStan en CI
Comme pour PHPCS, l’intérêt de PHPStan diminue fortement s’il n’est vérifié qu’occasionnellement. Une étape dédiée dans la CI, qui échoue le build en cas de nouvelle erreur, garantit que le niveau de rigueur choisi ne régresse jamais :
- name: Analyse statique PHPStan
run: vendor/bin/phpstan analyse --level=5 --no-progress
Sur nos projets, nous ne cherchons jamais à atteindre le niveau maximal de PHPStan à tout prix. Un niveau 5 ou 6 tenu dans la durée, sans régression, apporte beaucoup plus de valeur qu’un niveau 9 abandonné après deux semaines parce que personne n’a le temps de corriger les centaines d’erreurs restantes.
En résumé
PHPStan, associé à l’extension szepeviktor/phpstan-wordpress, comble un angle mort que ni les tests unitaires ni le linting de style ne couvrent : les incohérences de types et les cas limites non gérés. Démarrer à un niveau réaliste, ignorer explicitement les faux positifs légitimes, et intégrer l’analyse en CI en font un outil qui rapporte dès la première semaine d’utilisation, y compris sur un projet WordPress existant depuis des années.