Ce billet explique comment exécuter localement des grands modèles de langage (LLM) gratuitement avec Ollama, un outil simplifiant leur déploiement. L’auteur détaille l’installation via Docker, le téléchargement d’un modèle et son intégration dans une application Symfony grâce au Symfony AI Bundle, tout en évitant les pièges courants. L’objectif est de montrer qu’il est possible d’utiliser des LLM sans dépendre de fournisseurs externes payants, tout en maîtrisant les coûts et la confidentialité des données.
Ollama agit comme un runtime local, optimisant les modèles pour le matériel et exposant une API HTTP locale. Ses avantages principaux sont l’absence de coûts marginaux (seule l’électricité est consommée), la confidentialité des données (pas de transmission externe) et la portabilité (le même setup fonctionne en développement comme en production). Cependant, la qualité des réponses reste inférieure à celle des modèles cloud comme GPT-4, surtout pour des tâches complexes nécessitant une prose élaborée.
Le guide s’adresse aux développeurs PHP/Symfony et se concentre sur des cas d’usage concrets comme la génération de métadonnées SEO ou l’extraction de données structurées. Il mentionne aussi les prérequis matériels, soulignant que des modèles de plusieurs milliards de paramètres exigent une infrastructure adaptée, sans entrer dans des comparatifs techniques.
L’article explique comment créer un widget personnalisé pour Symfony Terminal afin d’afficher un GIF animé dans le terminal, en l’occurrence un chat dégoûté. L’auteur détaille les étapes techniques, comme l’extension de la classe AbstractWidget, l’implémentation de la méthode render() pour générer le rendu ligne par ligne, et l’utilisation du hook onAttach() pour animer l’image via le scheduler de Symfony. Le rendu repose sur des caractères demi-bloc ANSI (comme ▀) pour simuler une résolution verticale accrue, tout en restant compatible avec le système de composition de TUI.
L’auteur partage ensuite trois bugs rencontrés lors du développement, illustrant les défis techniques : un problème de transparence dans le GIF, une animation figée malgré des frames distinctes, et des difficultés liées à la gestion des couleurs. Ces obstacles sont résolus grâce à des ajustements comme la duplication correcte des frames ou la gestion des canaux alpha. Le billet souligne aussi l’importance de l’event loop de Symfony, qui permet d’animer l’image sans bloquer l’interactivité du terminal.
Enfin, l’article précise que ce widget reste expérimental et non optimisé pour une utilisation en production. Il s’agit avant tout d’une démonstration technique, sans prétention de performance ou de comparaison avec d’autres solutions TUI en Rust ou Python. L’auteur conclut en partageant un extrait de code et en mentionnant l’utilisation d’un hook Makefile pour automatiser les tests.
L’article explique pourquoi les architectures CRUD (Create, Read, Update, Delete) compliquent les tests unitaires et augmentent la charge cognitive des développeurs. L’auteur souligne que la logique métier, dispersée dans des contrôleurs, services, FormType ou événements Doctrine, devient difficile à identifier et à tester, favorisant la duplication de code et les erreurs. Les modifications nécessitent de comprendre des interactions complexes, ralentissant le développement et augmentant le risque de régressions.
L’auteur illustre ce problème avec des exemples concrets en Symfony, où des règles métiers se cachent dans des couches techniques variées (validations dans les formulaires, effets de bord dans les écouteurs Doctrine). Cette dispersion empêche une couverture de test efficace, car les tests doivent souvent simuler des dépendances externes (bases de données, envoi d’emails) plutôt que de se concentrer sur la logique pure.
Enfin, l’article critique l’illusion des services génériques, qui masquent la complexité sans résoudre le problème de fond. La solution proposée est de distinguer clairement les contrats d’entrée (validation des données) des invariants métiers (règles de transition), afin de structurer le code de manière plus testable et maintenable.
L’article de Nicolas Jourdan critique la pratique courante de lier directement les formulaires Symfony aux entités Doctrine, soulignant les problèmes d’architecture qui en découlent. L’auteur explique que cette approche crée un couplage implicite entre la couche de présentation (formulaire) et le modèle métier (entité), transformant cette dernière en simple transporteur de données HTTP. Bien que pratique à court terme, cette méthode introduit des tensions lorsque l’application évolue, notamment en mélangeant les responsabilités (validation, normalisation) et en rendant le code difficile à maintenir.
L’exemple concret d’un formulaire d’inscription à une conférence illustre ces limites. Les règles métier (comme la vérification de la capacité des sessions ou l’expiration des codes promo) finissent par être dispersées entre les contraintes du formulaire et celles de l’entité, complexifiant la logique et réduisant la clarté du code. L’auteur met en garde contre cette approche, qui semble initialement simple mais devient problématique sous la pression des évolutions produit.
Pour remédier à ces problèmes, Jourdan propose une séparation plus nette entre les formulaires et les entités, en utilisant des objets dédiés (DTO) pour capturer les données brutes de l’utilisateur avant de les transformer en entités métier. Cette méthode permet de préserver l’intégrité du domaine tout en gérant plus efficacement les interactions utilisateur, évitant ainsi les compromis architecturaux coûteux à long terme.
Cet article présente une approche optimisée pour le développement Symfony en utilisant des Dev Containers sans root, Xdebug 3.4 et PHP 8.4, afin d’améliorer l’expérience développeur (DX). L’auteur met en avant l’utilisation de FrankenPHP, un serveur d’applications performant en Go, remplaçant Nginx + PHP-FPM, pour des temps de réponse rapides. La solution repose sur des conteneurs isolés et sécurisés, évitant les problèmes de permissions classiques avec Docker.
L’accent est mis sur la compatibilité IDE (VS Code et PhpStorm) et la résolution des écueils courants, comme les conflits d’architecture ou les montages de volumes. Les conteneurs rootless résolvent les erreurs de permissions en mappant l’utilisateur du conteneur à l’utilisateur local, éliminant le besoin de commandes comme chmod -R 777.
Enfin, l’article détaille la création d’un projet Symfony 7.4 via un conteneur temporaire pour Composer, sans installation locale de PHP. Le choix de l’image Docker (Alpine vs Debian) est crucial pour éviter des incompatibilités avec certains IDE, comme les plantages de JetBrains.
En 2026, PHP et Symfony s’imposent comme une stack mature et performante pour les CTO, grâce à des évolutions majeures. PHP 8.5, avec ses fonctionnalités typées (property hooks, pipe operator) et son JIT optimisé, ainsi que Symfony 7 et son écosystème de plus de cinquante composants découplés, couvrent désormais tous les besoins modernes : API (API Platform), e-commerce (Sylius), back-office (EasyAdmin), temps réel (Mercure), interfaces réactives (Live Components) et même le mobile via Hotwire Native. L’outillage industriel (PHPStan, Rector, PHPUnit 13) garantit une qualité de code élevée, tandis que FrankenPHP révolutionne l’infrastructure avec un throughput 3 à 4 fois supérieur à PHP-FPM et une latence divisée par cinq en mode worker.
L’auteur, CTO freelance avec quatorze ans d’expérience, souligne que cette stack n’est plus un compromis nostalgique mais une option par défaut, adaptée aux SaaS, applications métiers complexes ou projets IA-first. L’écosystème Symfony, autrefois perçu comme fragmenté, s’est structuré pour offrir une solution cohérente, réduisant les délais de développement et simplifiant la maintenance grâce à une expertise accumulée.
L’article s’adresse aux CTO et lead tech en quête d’une vision actualisée, mettant en avant la maturité de PHP/Symfony en 2026 : un langage strict et performant, un framework complet et un outillage industriel, le tout sans nécessiter de superposer des technologies front-end ou mobiles.
Ce billet explique comment concevoir un menu d'administration efficace avec EasyAdmin dans Symfony, en s'appuyant sur l'expérience de l'auteur qui a retravaillé quatre fois son menu en deux ans pour éviter une dette d'usage quotidienne. L'objectif est de structurer un menu robuste et maintenable, en se concentrant sur la méthode configureMenuItems() du DashboardController, qui génère dynamiquement le menu sans configuration externe. L'article met en avant trois bonnes pratiques : organiser le menu pour qu'il résiste à la croissance, distinguer les trois types de liens (linkTo, linkToUrl, linkToDashboard), et conditionner l'affichage des éléments en fonction des rôles utilisateurs.
L'auteur détaille les trois familles de constructeurs de MenuItem : linkTo pour les CRUD, linkToUrl pour les liens externes ou personnalisés, et linkToDashboard pour le tableau de bord. Il souligne l'importance de la lisibilité et de la simplicité, en évitant la sur-organisation qui alourdit la navigation. Le billet aborde aussi des astuces comme l'utilisation de yield pour une génération dynamique du menu et l'ajout d'icônes compréhensibles en un coup d'œil. Enfin, il met en garde contre l'usage inutile de setPermission(), préférant une gestion des rôles plus intuitive.
En mai 2026, le portail moncompte.ants.gouv.fr a subi une faille IDOR (Insecure Direct Object Reference) ayant exposé les données de 11,7 millions de Français. L’exploitation, qualifiée de « vraiment stupide » par son auteur, consistait simplement à modifier un identifiant numérique dans une URL pour accéder aux comptes d’autres utilisateurs, faute de vérification d’autorisation entre l’authentification et la récupération des données.
L’article explique que cette vulnérabilité, courante mais critique, survient lorsque les applications ne contrôlent pas si un utilisateur a le droit d’accéder à une ressource spécifique, même après s’être authentifié. L’exemple donné illustre un endpoint /api/account/{id} où seule la session est validée, sans vérification que l’identifiant {id} correspond bien au compte de l’utilisateur connecté.
Pour éviter ce type de faille, l’auteur propose des solutions techniques avec Symfony et PHP, comme l’utilisation de Voters pour gérer les autorisations, l’absence d’IDs exposés dans les URLs, ou des tests automatisés pour détecter les accès non autorisés. Le problème ne dépend pas du framework utilisé, mais de l’absence d’une couche d’autorisation explicite.
Symfony AI Mate est une extension pour Symfony qui introduit un troisième port d'entrée dans les applications, permettant une communication via JSON-RPC sur stdio avec des agents externes comme des IDE ou des chatbots. Contrairement aux ports HTTP ou console existants, cette solution n'ouvre aucun port réseau, fonctionnant comme un sous-process qui communique directement via les flux stdin/stdout, ce qui améliore la sécurité et simplifie le déploiement.
L'installation est minimaliste : trois commandes Composer suffisent pour intégrer l'outil, qui génère ensuite une configuration de base et une documentation pour les agents. L'extension expose les services Symfony, les logs et le profilage à des clients compatibles avec le protocole MCP, comme les assistants de code (Claude Code, Junie) ou des scripts automatisés.
L'approche repose sur un wrapper exécuté à la demande par le client, évitant toute infrastructure serveur persistante. Les outils disponibles peuvent être étendus via des extensions dédiées, comme celles pour Symfony ou Monolog, offrant ainsi une flexibilité pour des usages variés, allant de l'aide au développement à l'automatisation de tâches.
Le composant Form de Symfony est jugé efficace pour les cas simples mais rapidement complexe dès qu’on s’en écarte, notamment à cause du couplage entre logique métier, contrôleurs et interface, ce qui motive une approche alternative visant à mieux séparer les responsabilités. L’article propose de s’appuyer sur les nouveaux mécanismes comme MapQueryString et MapRequestPayload pour introduire un attribut personnalisé MapFormState qui hydrate un DTO, gère la validation et transmet au contrôleur à la fois les données et les erreurs, laissant ce dernier se concentrer uniquement sur le traitement métier tandis que les templates Twig gèrent entièrement l’affichage. Cette approche rapproche le fonctionnement d’une architecture découplée type Symfony + front moderne, en simplifiant la gestion des formulaires et en évitant la lourdeur des FormType traditionnels.
Personnaliser un bundle Symfony sans modifier le code vendor repose sur le choix du bon point d’extension et sur des techniques qui restent robustes face aux mises à jour, en privilégiant d’abord la configuration native quand elle existe pour éviter toute complexité inutile. Lorsque cela ne suffit pas, plusieurs approches propres sont proposées : redéfinir une route avec une priorité plus élevée pour remplacer un contrôleur, surcharger des templates via templates/bundles/ (en pouvant étendre le template original pour limiter la duplication), ou décorer un service afin d’ajouter du comportement autour de l’existant sans le remplacer. L’objectif commun est d’isoler les adaptations dans son propre code tout en conservant la compatibilité et la maintenabilité du projet lors des évolutions du bundle.
Le pattern Chain of Responsibility permet de traiter une requête via une chaîne de handlers indépendants, chacun appliquant une responsabilité précise puis décidant de continuer ou d’interrompre le traitement, ce qui découple totalement l’émetteur de la logique de traitement et facilite l’extension ou la réorganisation du flux. Dans un contexte Symfony, il sert à remplacer des méthodes monolithiques pleines de conditions (authentification, validation, règles métier, etc.) par une succession de services spécialisés manipulant un même objet (DTO), configurés via des tags et priorités pour contrôler l’ordre d’exécution. Cette approche améliore la maintenabilité, la réutilisation et la testabilité, tout en permettant d’ajouter facilement de nouvelles étapes ou pipelines sans modifier le code existant.
Ce billet explique comment installer et configurer EasyAdmin sur Symfony pour créer rapidement un back-office efficace. L’auteur souligne que ce bundle est idéal pour administrer 2 à 30 entités Doctrine avec un CRUD générique, sans alourdir le projet, contrairement à des solutions comme Sonata ou API Platform Admin, plus complexes ou spécialisées.
L’installation se fait en une seule commande Composer, suivie de la génération automatique d’un DashboardController via une commande Symfony. Le bundle propose ensuite une configuration minimale pour accéder à l’interface d’administration dès le départ.
L’article met en avant la simplicité d’EasyAdmin, qui évite une configuration lourde tout en restant flexible pour des personnalisations basiques, ce qui en fait un choix pertinent pour les projets où l’admin est un outil et non un produit à part entière.
L’article explique la migration d’un outil de génération de PDF, wkhtmltopdf, vers Gotenberg dans une application Symfony legacy, en évitant de perturber les endpoints existants. L’idée principale est de découpler la génération de PDF du conteneur API pour améliorer les performances et la maintenabilité, car wkhtmltopdf consommait trop de ressources CPU et reposait sur des dépendances locales (fichiers, polices, images). Le processus a nécessité de refactoriser l’architecture pour externaliser le rendu HTML vers un conteneur dédié, tout en gérant les différences de rendu entre les moteurs (problèmes de polices, de mise en page ou de chemins d’accès).
La migration a révélé des défis techniques, comme la gestion des chemins de fichiers (remplacement des références locales par des URLs accessibles) et les écarts de rendu entre wkhtmltopdf et Chromium (Gotenberg), entraînant des modifications de mise en page inattendues. L’approche adoptée a consisté à migrer progressivement, type de document par type de document, pour limiter les risques et permettre des ajustements fins. L’objectif était de préserver la compatibilité des endpoints tout en améliorant l’infrastructure.
L’article propose une solution pour tester efficacement le JavaScript dans Symfony Asset Mapper, souvent confronté à des erreurs comme ERR_MODULE_NOT_FOUND en raison de l’incompatibilité entre l’importmap.php de Symfony et les outils Node.js. L’auteur suggère d’utiliser des liens symboliques pour faire correspondre les fichiers Symfony (dans assets/vendor ou vendor) avec la structure attendue par Node.js dans node_modules, évitant ainsi de dupliquer ou modifier les imports.
Un script PHP automatise la création de ces liens symboliques en analysant l’importmap.php, permettant à Node.js de résoudre les modules comme en production. Cette méthode s’intègre via un pretest dans le package.json, exécutant le script avant chaque test. L’approche privilégie le test runner natif de Node.js (depuis la version 20) pour sa simplicité, sa rapidité et son absence de configuration complexe, tout en testant les fichiers réels utilisés en production.
Twig 3.24.0, sorti avec Symfony 7.4, introduit des fonctionnalités avancées pour simplifier la création de composants UI réutilisables, répondant aux besoins des systèmes de design modernes et des frameworks comme Tailwind. Parmi les nouveautés, la fonction html_attr, la stratégie d'échappement html_attr_relaxed et les opérateurs null-safe améliorent la gestion des attributs HTML et des données dynamiques, réduisant ainsi la complexité des templates.
L'article explique comment abandonner les tableaux non structurés pour des DTOs strictement typés et validés, combinés à des attributs PHP 8.x et à Symfony 7.4's #[MapRequestPayload], afin de transmettre des données propres et validées directement aux templates Twig. Cela renforce la robustesse des applications tout en maintenant une bonne expérience de développement.
Pour utiliser ces fonctionnalités, il est nécessaire d'installer les packages twig/html-extra, symfony/serializer et symfony/validator, et de vérifier que Twig 3.24.0 ou supérieur est bien installé. L'article détaille également la configuration requise et présente un exemple concret de création d'un composant Button avec des DTOs stricts.
Ce billet présente une méthode pour déployer rapidement des applications Symfony en production grâce à une combinaison d'outils modernes. L'auteur souligne d'abord l'accélération du développement grâce à l'IA, qui permet de créer des prototypes fonctionnels en quelques heures, mais souligne que l'infrastructure doit suivre pour éviter un goulot d'étranglement. Il propose ensuite Once, un outil open source de 37signals, qui automatise le déploiement d'applications Docker sur un seul serveur via un reverse proxy intégré et une gestion automatique des certificats SSL.
L'article détaille l'installation simplifiée de Once, qui repose sur Docker et Kamal, et son fonctionnement avec un wildcard DNS pour attribuer automatiquement un sous-domaine à chaque nouvelle application déployée. Cette approche élimine les configurations manuelles de reverse proxy ou de certificats, permettant un déploiement en quelques minutes après un simple git push.
Enfin, l'auteur explique pourquoi il a adopté FrankenPHP, un runtime PHP intégré à Caddy, qui remplace avantageusement la stack classique (Nginx, PHP-FPM, Mercure) par un seul conteneur. Grâce à l'IA, la génération et le débogage des fichiers Dockerfile sont devenus accessibles, rendant cette solution à la fois performante et simple à mettre en œuvre pour des projets PHP modernes.
Les LiveComponents de Symfony offrent une solution efficace pour créer des interfaces dynamiques sans recourir à des bibliothèques front-end lourdes, en s'appuyant sur des attributs Twig et une stack simple. Leur simplicité d'utilisation, comme l'ajout d'attributs pour des fonctionnalités comme l'édition inline ou le live reload, les rend attractifs pour les développeurs back-end peu enclins au développement front-end. Cependant, leur utilisation intensive révèle des limites, notamment en matière de sérialisation des objets Doctrine complexes, comme les collections ou les relations entre entités.
L'auteur illustre ces limites avec un exemple concret où la sérialisation d'une collection d'entités Loan échoue, obligeant à recourir à des solutions comme l'activation du sérialiseur ou la définition de types concrets. Cette problématique, bien que simplifiée par rapport à une architecture front-end classique, montre que la promesse d'une solution "tout-en-un" s'effrite face à des cas d'usage avancés, comme la gestion de fichiers ou de collections complexes. Les LiveComponents, bien que puissants pour des démonstrations, révèlent des contraintes techniques qui peuvent compliquer leur adoption à grande échelle.
La sortie de Symfony UX 3.0.0 marque une évolution majeure en abandonnant les dépendances obsolètes de la version 2.x et en relevant les exigences minimales à PHP 8.4 et Symfony 7.4. Cette version se concentre sur des composants Twig robustes, une intégration frontend-backend fluide et des standards web natifs, simplifiant ainsi le développement sans JavaScript personnalisé.
L’article propose un tutoriel pratique pour créer une plateforme immobilière moderne en exploitant les nouvelles fonctionnalités, comme les composants Twig, l’autocomplétion pour les commodités et l’outil Cropper.js pour les galeries d’images. L’installation repose sur des packages spécifiques, avec une vérification des composants via la commande debug:twig-component.
Enfin, l’exemple illustre la création d’un composant réutilisable PropertyCard en PHP 8.4, utilisant des attributs et des classes CSS dynamiques via la fonction html_cva de twig/html-extra, pour un rendu optimisé et maintenable.
L’article explique comment optimiser la gestion de gros fichiers JSON dans Symfony pour éviter les problèmes de mémoire, notamment l’OOM killer. L’idée principale repose sur l’utilisation du composant natif symfony/json-streamer de Symfony 7.4, qui permet de parser les données en flux continu plutôt que de charger l’intégralité du fichier en mémoire. Cette approche réduit drastiquement l’empreinte mémoire, évitant les pièges des méthodes traditionnelles comme json_decode() ou le Serializer, qui dupliquent les données en mémoire.
L’auteur détaille les mécanismes sous-jacents, comme le fonctionnement en DOM des méthodes classiques, qui consomment jusqu’à cinq fois plus de RAM que la taille du fichier initial. À l’inverse, le streaming lit les données octet par octet et ne conserve en mémoire que les éléments actuellement traités, grâce à des DTOs (Data Transfer Objects) typés et à l’attribut #[JsonStreamable]. Cette méthode est particulièrement adaptée aux fichiers de plusieurs gigaoctets ou aux webhooks massifs.
Pour implémenter cette solution, l’article recommande d’installer trois composants Symfony (json-streamer, type-info et object-mapper) et d’exploiter leur intégration native. L’architecture repose sur des Generators PHP, qui libèrent automatiquement la mémoire après traitement de chaque objet, garantissant une consommation constante et minimale.