Qualité de code : le quatuor infernal PHPStan, Rector, CS Fixer, Biome
Ne laissez plus passer de bugs. Découvrez ma configuration Level Max pour PHPStan, Rector, CS Fixer et Biome.
Publié le
Temps de lecture 4 min
La dette technique n'est pas une fatalité. C'est souvent juste un manque d'outillage. J'ai mis en place une pipeline de qualité drastique. Pas pour me flageller, mais pour déléguer la rigueur à des machines.
Voici mes quatre gardiens du temple.
PHPStan : l'analyse statique (niveau max ou rien)
L'époque où l'on découvrait une NullPointerException en production parce qu'un utilisateur avait un email vide est révolue. Ou du moins, elle devrait l'être.
Sur ce blog, j'ai activé le mode "paranoïaque" de PHPStan : Level Max. Au début, ça fait mal. Vous lancez l'outil, et il vous insulte avec 400 erreurs rouges. "Call to a member function getTime() on null", "Method expects User, User|null given".
Votre premier réflexe ? "C'est bon, je sais que ça ne sera pas null ici !". Spoiler : Vous avez tort.
La réalité, c'est que PHPStan a raison. Si il existe une infime chance qu'une variable soit nulle, le bug arrivera.
Voici ma configuration de combat dans phpstan.neon :
parameters:
level: max
paths:
- src
# On force le traitement des PHPDoc comme incertain
# Ca nous oblige à typer proprement en PHP natif
treatPhpDocTypesAsCertain: false
Rector : l'architecte de la modernisation
Migrer vers PHP 8.4 manuellement ? Jamais de la vie. Rector est mon outil de "Refactoring Automatique". C'est un robot qui lit l'AST (Abstract Syntax Tree) de votre code et applique des règles de transformation.
Exemple concret : sur Lecodeestdanslepre, j'ai lancé Rector avec le set UP_TO_PHP_84.
En 30 secondes, il a transformé mes propriétés en readonly, remplacé mes fonctions anonymes par la syntaxe (...) =>, et nettoyé le code mort.
Mais attention, il faut le dompter. J'ai dû exclure certaines règles dans rector.php pour éviter qu'il ne casse mes constructeurs Doctrine.
PHP-CS-Fixer : le tyran du style
Si Rector est l'architecte, PHP-CS-Fixer est le décorateur d'intérieur maniaque. Son job n'est pas de changer la logique, mais de s'assurer que chaque virgule est à sa place.
Sur ce projet, il n'est pas là pour faire joli. Il optimise :
// .php-cs-fixer.dist.php
$config->setRules([
// Force le mode strict partout (PHP 7+)
'declare_strict_types' => true,
// Performance : Ajoute un \ devant les fonctions natives
// \strlen() est plus rapide que strlen() car PHP ne cherche pas dans le namespace courant
'native_function_invocation' => ['include' => ['@compiler_optimized']],
// Risky rules : On autorise les fix qui modifient le code
'@Symfony:risky' => true,
]);
Grâce à lui, je ne débat plus jamais de "où mettre l'accolade" en Review. C'est automatisé.
Biome : la révolution Rust
Côté JS, c'était le chaos avec ESLint et Prettier. J'ai tout viré pour Biome.
Pourquoi ? Parce que c'est écrit en Rust.
La différence de vitesse est telle qu'on croit que la commande a planté.
Checked 45 files in 4ms.
Attendez, 4 millisecondes ? Oui.
Et le meilleur ? Sur ce projet, je n'ai même pas installé Node.js.
J'utilise le package Composer kocal/biome-js-bundle.
Il télécharge le binaire Biome (comme AssetMapper le fait pour Tailwind) et me permet de lancer mes checks directement depuis PHP.
composer require --dev kocal/biome-js-bundle
Pas de node_modules, pas de package.json. Juste un binaire ultra-rapide piloté par PHP.
Mon workflow : la discipline par Castor
Avoir des outils, c'est bien. Les utiliser, c'est mieux. Pour éviter le syndrome de l'oubli, tout est centralisé dans Castor, notre task runner moderne.
// .castor/qa.php
#[AsTask(description: 'Auto-fix all QA issues')]
function fix(): void
{
io()->title('Auto-fixing all QA issues');
// ...
run('docker compose exec php vendor/bin/php-cs-fixer fix');
run('docker compose exec php bin/biome check --write --unsafe assets/');
run('docker compose exec php vendor-bin/rector/vendor/rector/rector/bin/rector process');
}
Je lance castor qa:fix avant chaque git push. C'est devenu un réflexe pavlovien. La machine nettoie derrière moi, et je peux me concentrer sur ce qui compte : la valeur métier.