🐘PHP : retrouver le confort du typage statique
Créé par Jean-Emmanuel Bissey le 04/11/2026 PubliéAu début des années 2000, développer en PHP avec comme seul super outil Vim et sa coloration syntaxique, c'était parfois du sport !
À cette époque, le langage était beaucoup moins structuré qu'aujourd'hui. Un simple renommage de champ dans une table de la base de données pouvait provoquer une erreur à l'exécution, parfois à un endroit complètement inattendu.
Et bien entendu, les utilisateurs ne manquaient pas de vous le rappeler : « Encore un bug ! »
Il fallait alors partir à la chasse aux erreurs, souvent à tâtons, avec pour seule aide les messages affichés à l'écran ou quelques echo bien placés.
La découverte du confort de C#
Au début des années 2010, je suis passé au C# avec Visual Studio. Quel soulagement !
Le typage statique, l'autocomplétion, la navigation dans le code et surtout les possibilités de refactoring changeaient complètement la façon de travailler.
Renommer une propriété utilisée dans plusieurs dizaines de fichiers ? Aucun problème : Visual Studio savait retrouver les références et effectuer le travail proprement.
Et surtout, beaucoup d'erreurs étaient détectées avant même de lancer le programme.
On finit par prendre goût à ce confort.
Le retour à PHP pour MyClub
En 2025, lorsque j'ai commencé MyClub, je souhaitais développer une application web. J'avais envisagé de rester dans l'univers C#, mais les solutions que j'avais étudiées, notamment autour de MAUI et Razor, me semblaient vraiment trop lourdes pour mon projet.
J'ai donc choisi de revenir à PHP.
Comme je l'expliquais dans mon précédent article, De C# à PHP : le grand écart pour développer MyClub, ce retour n'a pas été sans difficultés.
PHP avait beaucoup évolué, mais il restait une différence fondamentale avec C# : son fonctionnement dynamique et son absence de vérification statique native comparable à celle d'un compilateur C#.
Je ne souhaitais pourtant pas abandonner les habitudes que j'avais prises pendant toutes ces années.
Trouver une architecture simple
Pour une application web, le recours à un routeur devient rapidement indispensable. Je ne voulais cependant pas me lancer dans un framework complet comme Laravel ou Symfony. Ces solutions sont certainement très intéressantes, mais elles apportaient à mes yeux une complexité dont je n'avais pas besoin.
J'ai découvert FlightPHP, un micro-framework qui correspondait parfaitement à mes attentes : gérer les routes, organiser les contrôleurs et laisser le développeur libre de ses choix d'architecture.
Pour les vues, j'ai choisi Latte, un moteur de templates qui permet de séparer proprement le traitement des données de leur présentation.
J'utilise également Tracy pour le débogage.
Au final, une pile technique relativement légère :
- PHP pour le langage ;
- FlightPHP pour le routage ;
- Latte pour les vues ;
- SQLite pour la base de données ;
- Tracy pour le débogage.
Pas besoin d'en faire davantage pour commencer.
Mais choisir des outils simples ne signifie pas pour autant écrire du code sans contraintes.
Les Value Objects : donner un sens aux données
C'est probablement l'un des changements les plus importants dans ma manière de développer en PHP.
Je souhaite éviter autant que possible les tableaux associatifs et les objets génériques dont on ne connaît pas réellement le contenu.
Une requête SQL retourne traditionnellement un ensemble de données. On peut très bien récupérer le résultat sous forme d'objet générique et le transmettre de fonction en fonction.
- Mais que contient réellement cet objet ?
- Quels sont ses champs ?
- Quel est leur type ?
- Certains peuvent-ils être absents ?
Il suffit qu'une requête évolue pour que plusieurs parties de l'application se retrouvent avec des données différentes de celles qu'elles attendaient, J'ai donc pris l'habitude de créer des Value Objects pour représenter les données manipulées par l'application. On sait ainsi précisément ce que contient l'objet et ce que l'on peut en attendre.
Cela demande un peu plus de travail au départ, mais les bénéfices sont importants.
Les ViewModels : séparer les données de leur présentation
J'applique la même logique aux vues.
Un contrôleur ne devrait pas transmettre à une vue une multitude de variables disparates, parfois difficiles à identifier et à maintenir. Je préfère construire un ViewModel, c'est-à-dire un objet qui contient exactement les informations nécessaires à l'affichage d'une page.
Le contrôleur prépare les données, construit le ViewModel et le transmet à Latte. La vue n'a donc pas à connaître les détails de la base de données ni les traitements nécessaires pour obtenir les informations.
Cette séparation présente plusieurs avantages :
- les responsabilités sont mieux définies ;
- les données attendues par une vue sont explicites ;
- les modifications sont plus faciles à maîtriser ;
- l'analyse statique peut vérifier une bonne partie des échanges entre les différentes couches.
C'est une approche que je connaissais déjà avec le développement C# et le pattern MVVM. Je retrouve ici une partie de cette philosophie, adaptée au fonctionnement d'une application web.
PHPStan : le chaînon manquant
Mais les Value Objects et les ViewModels ne suffisent pas.
Il fallait encore disposer d'un outil capable de vérifier que le code respecte réellement les types annoncés.
C'est là qu'intervient PHPStan.
PHPStan analyse le code PHP sans avoir besoin de l'exécuter. Il est capable de détecter de nombreuses incohérences : mauvais types de paramètres, valeurs de retour incorrectes, propriétés inexistantes, variables potentiellement nulles, etc.
J'ai progressivement augmenté le niveau d'analyse jusqu'à atteindre le niveau maximum.
Et là, les choses deviennent intéressantes ! PHPStan oblige à être précis. Il ne suffit plus de déclarer qu'une méthode retourne un tableau si, en réalité, on attend une collection d'objets bien particuliers. Il faut décrire précisément les types manipulés. Et si une modification dans une méthode provoque une incohérence ailleurs dans le programme, l'analyse permet souvent de la détecter immédiatement.
C'est exactement le genre de sécurité que j'appréciais avec C#.
Une discipline qui demande quelques efforts
Bien entendu, cette approche a un coût.
Il faut créer davantage de classes, définir les propriétés, préciser les types de retour et parfois passer un peu de temps à satisfaire PHPStan.
Les tableaux associatifs sont pratiques, mais ils deviennent vite difficiles à maîtriser dans une application importante.
Les objets génériques permettent d'aller vite, mais ils repoussent parfois les problèmes à l'exécution.
Et les méthodes qui retournent un peu n'importe quoi sont évidemment à éviter !
Je ne prétends pas que cette approche soit la meilleure pour tous les projets. C'est simplement une façon de travailler qui me convient beaucoup mieux.
Et finalement, PHP devient plutôt agréable !
Aujourd'hui, MyClub utilise systématiquement des Value Objects et des ViewModels, des types explicites et declare(strict_types=1).
L'ensemble est contrôlé par PHPStan au niveau maximum.
PHP reste un langage dynamique. PHPStan ne transforme pas PHP en langage compilé et ne peut évidemment pas garantir l'absence de toutes les erreurs à l'exécution.
Mais en combinant ces différents outils, on obtient un environnement de développement nettement plus sécurisant.
Je retrouve une bonne partie du confort que j'avais avec Visual Studio et C#. Et surtout, lorsque je modifie une partie de MyClub, je peux lancer l'analyse statique et obtenir rapidement une liste des endroits où mes changements ont provoqué des incohérences.
C'est particulièrement appréciable pour une application qui dépasse désormais largement le stade du petit projet personnel.
Finalement, je suis revenu à PHP pour sa simplicité, mais j'ai conservé de mes années C# une exigence qui m'est devenue indispensable : je préfère que les erreurs soient détectées pendant le développement plutôt que par les utilisateurs !