PHPStan level 9 (ou max), c’est la promesse d’un code PHP aussi rigoureux qu’un projet TypeScript strict. Mais sur un projet legacy de 500 fichiers, lancer PHPStan à level 9 d’un coup génère souvent des milliers d’erreurs. De quoi décourager n’importe quelle équipe. Voici une stratégie progressive et réaliste pour y arriver.
Pourquoi PHPStan level 9 ?
Chaque level de PHPStan ajoute des vérifications supplémentaires. Au level 0, PHPStan vérifie les erreurs de base (classes inexistantes, méthodes inconnues). Au level 9, il vérifie les types génériques, les types de retour de closures, interdit le type mixed implicite, et valide les formes de tableaux. C’est la différence entre « le code fonctionne » et « le code est prouvé correct par analyse statique ».
La stratégie incrémentale
Ne tente jamais de passer directement de 0 à 9. La stratégie gagnante :
- Commencer au level 0 et corriger toutes les erreurs
- Monter d’un level, corriger, commiter, répéter
- Les levels 0-5 passent généralement vite
- Les levels 6-8 demandent du travail sur les types
- Le level 9 nécessite des génériques et des array shapes
Compte en moyenne 2 à 8 heures par level selon la taille du projet. Intègre chaque montée de level comme un ticket de sprint normal.
Le fichier baseline : ton filet de sécurité
Le baseline est la fonctionnalité clé pour les projets legacy. Il enregistre toutes les erreurs existantes et ne fait échouer la CI que sur les nouvelles erreurs.
# Générer le baseline
vendor/bin/phpstan analyse --level=5 --generate-baseline
# Le fichier phpstan-baseline.neon est créé
# Ajoutez-le à votre config# phpstan.neon
includes:
- phpstan-baseline.neon
parameters:
level: 5
paths:
- src
checkGenericClassInNonGenericObjectType: true
checkMissingIterableValueType: trueVotre dette technique s'accumule ?
Demander un audit →Avec le baseline, tu peux monter immédiatement au level souhaité en CI, et résorber les erreurs legacy progressivement. Chaque correction réduit le baseline. L’objectif : un baseline à zéro.
Les patterns qui cassent aux niveaux élevés
Voici les problèmes les plus fréquents à partir du level 6 :
- Types mixed implicites — PHPStan exige des types explicites partout. Ajoute des
@paramet@returnou mieux, des type declarations PHP natifs. - Array shapes —
arrayne suffit plus. Il fautarray{name: string, age: int}oulist<User>. - Génériques Doctrine — Les repositories Doctrine nécessitent
@extends ServiceEntityRepository<User>. - Closures non typées — Chaque closure doit avoir ses paramètres et retours typés.
- Magic methods —
__get,__callet consorts nécessitent des PHPDoc précis.
Intégration CI/CD
PHPStan doit faire partie de ta pipeline CI au même titre que les tests. Voici une configuration minimale :
# .github/workflows/quality.yml
jobs:
phpstan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: 8.3
- run: composer install --no-interaction
- run: vendor/bin/phpstan analyse --no-progressLe flag --no-progress supprime la barre de progression (inutile en CI). Ajoute --error-format=github pour que les erreurs s’affichent directement comme annotations sur la PR.
PHPStan dans un workflow d’audit
Le nombre d’erreurs PHPStan par fichier est l’une des métriques clés d’un audit de qualité de code. Un projet avec moins de 0.5 erreur/fichier au level max est considéré en bon état. Au-delà de 2 erreurs/fichier, il y a un problème structurel. Bear Scan intègre l’analyse PHPStan comme l’une de ses métriques dans le scoring A-F, avec des recommandations de montée de level et un chiffrage de l’effort associé.
Votre dette technique s'accumule ?
Audit complet en 10 jours. Recommandations priorisées et actionnables.