La semaine dernière, une lectrice m'a écrit avec une capture d'écran de sa CI : PHP-CS-Fixer, PHP_CodeSniffer, PHPStan au niveau 8, Deptrac, tous alignés les uns derrière les autres, onze minutes avant que quiconque sache si une faute de frappe dans un docblock avait cassé le build. Sa question tenait en une ligne : devait-elle tout arracher et mettre Mago à la place ? Ma réponse, c'est non, pas tout, et pas ce trimestre. Ce qu'elle devrait faire dès demain matin, c'est ajouter Mago à son hook pre-commit et lui confier entièrement le formatage et le linting.
Un peu de contexte si tu n'es pas encore tombé dessus. Mago est un binaire statique unique écrit en Rust par Carthage Software, qui regroupe un formateur (mago fmt, PER-CS par défaut, avec des presets psr-12, laravel et drupal), un linter (mago lint, 190 règles réparties en 9 catégories dans la version 1.51.2), un analyseur statique (mago analyze, qui lit les annotations PHPStan et Psalm, génériques et types conditionnels compris) et un garde-fou architectural (mago guard, qui couvre le terrain occupé aujourd'hui par Deptrac et PHPArkitect). Tout tient dans un seul mago.toml, le projet est en 1.x stable depuis décembre 2025 et il est sous licence MIT ou Apache 2.0. Tu peux l'installer avec composer require --dev carthage-software/mago, ou te passer complètement du runtime PHP grâce au script d'installation.
Le chiffre que tout le monde reprend vient des benchmarks du projet lui-même : un linting environ 29 fois plus rapide que PHP-CS-Fixer, grâce au code natif et à un pipeline réparti sur tous les cœurs. Les benchmarks maison méritent un sourcil levé, c'est vrai, mais même si ta base de code n'en voit qu'un tiers, le changement est plus important qu'il n'y paraît. Une vérification qui prend quarante secondes vit dans la CI, et tout le monde l'ignore jusqu'à ce que le pipeline passe au rouge. Une vérification qui prend moins de deux secondes peut tourner à chaque sauvegarde, et d'un coup les débats sur le formatage en revue de code disparaissent, parce que le diff n'en contient plus jamais. C'est la vitesse qui décide où une vérification a le droit de vivre, et c'est là que Mago gagne sa place en premier.
Maintenant, le meilleur argument pour tout miser dessus, parce qu'il tient la route. Sept outils, ça veut dire sept configs qui divergent, sept parseurs qui ne sont pas d'accord sur les cas limites de la nouvelle syntaxe, et un composer.json bourré de dépendances de dev qui se battent entre elles à chaque mise à jour mineure de PHP. Un seul parseur partagé par toutes les vérifications, c'est franchement de l'ingénierie plus propre. Et le guard est discrètement excellent : pouvoir écrire dans la config que tout ce qui se trouve sous App\Controller doit être final et nommé *Controller, ou que App\Domain ne peut dépendre que de lui-même et de PHP natif, sans outil séparé ni dialecte YAML de plus, c'est exactement le genre de chose dont les équipes parlent pendant des années sans jamais la mettre en place. Si tu n'as jamais imposé de découpage en couches parce que Deptrac te semblait être un truc de plus à surveiller, Mago abaisse sérieusement la barre.
Voici pourquoi je garde quand même PHPStan dans le pipeline pour l'instant. La valeur de mon analyse ne vient pas seulement du moteur : elle vient de l'extension Symfony qui sait ce que renvoie le conteneur, de l'extension Doctrine qui comprend mes repositories, et de trois ans de baseline que j'ai fait reculer entrée par entrée. Les mainteneurs de Mago eux-mêmes citent PHPStan et Psalm comme sources d'inspiration et ne prétendent pas encore égaler cet écosystème d'extensions. Si tu changes d'analyseur sans vérifier cette couverture, tu obtiendras l'un de ces deux résultats : une avalanche de faux positifs qui apprend à ton équipe à ignorer l'outil, ou le silence là où il y avait un vrai avertissement. Ni l'un ni l'autre n'apparaît sur un graphique de benchmark.
Mon partage est donc ennuyeux, et ça me va très bien. Formateur et linter : confie-les à Mago, lance mago format --check et mago lint dans le hook et dans la CI, utilise une baseline pour les recoins legacy, et appuie-toi sur mago lint --explain quand quelqu'un demande pourquoi une règle s'est déclenchée. Guard : adopte-le si tu n'as rien, quitte Deptrac à ton rythme si tu l'utilises. Analyseur : fais tourner mago analyze à côté de ton outil actuel pendant quelques sprints, compare ce que chacun remonte, et ne retire l'ancien qu'une fois que l'écart est quelque chose que tu sais nommer et accepter. Un conseil pratique pendant que tu es dans mago.toml : écris php-version = "8.3" avec les guillemets, parce que TOML lit 8.3 sans guillemets comme un nombre flottant alors que Mago attend une chaîne. Sinon, ça te coûtera dix minutes de perplexité.
Il y a une question plus diffuse derrière tout ça, que je n'arrête pas de ruminer. Nos outils de qualité ont toujours été écrits en PHP, ce qui veut dire que n'importe lequel d'entre nous pouvait ouvrir le code d'un sniff ou d'une règle PHPStan, le comprendre et envoyer un correctif un vendredi après-midi. Mago fait passer le moteur en Rust, et les gens de Go te diront que c'est tout simplement comme ça qu'on construit de l'outillage rapide aujourd'hui. Soit. Mais si l'outillage PHP est arrivé jusqu'ici, c'est parce que ses utilisateurs pouvaient mettre les mains dedans, et j'aimerais savoir si ça survit quand la règle que tu veux ajuster se trouve dans une crate.
Alors voilà ce que j'aimerais vraiment lire dans les commentaires : si tu as déjà fait tourner mago analyze sur une vraie base de code Symfony ou Laravel en parallèle de PHPStan, qu'est-ce qu'il a attrapé que PHPStan avait raté, qu'est-ce qu'il a raté que PHPStan attrapait, et l'écart était-il assez faible pour que tu fasses la bascule ?




Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.