Retour Rapport final

Stage de 2ème année
Licence Pro MIAW

Kajite Bilâl  ·  Licence Métiers de l'informatique – Applications Web  ·  Université de Limoges


Introduction

Ce rapport final clôt mon stage de seconde année de Licence Professionnelle Métiers de l'Informatique — Applications Web, effectué du 30 mars au 29 mai 2026 au sein de THF-ES, bureau d'étude spécialisé dans le secteur des télécommunications situé à Provins (Seine-et-Marne). Il prolonge le rapport de lancement remis en début de mission et présente l'aboutissement du projet THF Operations Telecom Project, une application web sur mesure destinée à digitaliser l'ensemble des rapports d'intervention terrain de l'entreprise.

À l'issue de ces deux mois, l'application est déployée en production sur les serveurs Infomaniak, utilisée par les équipes, et couvre les quinze types de rapports métier initialement identifiés dans la solution propriétaire qu'elle vient remplacer. Ce document décrit le projet livré, revient sur le planning suivi, propose une analyse du travail réalisé et dresse un bilan personnel des compétences acquises au cours de cette expérience.

42 621

Sites référencés

15

Handlers métier

10+

Commits déployés

100 %

Périmètre Kizeo couvert


Description du projet et des missions réalisées

Rappel du contexte

THF-ES est un bureau d'étude d'une quarantaine de collaborateurs, dont plus de la moitié sont des techniciens itinérants intervenant quotidiennement sur des installations télécom — pylônes, toits techniques, antennes relais — réparties sur l'ensemble du territoire français. L'entreprise travaille pour le compte de donneurs d'ordre majeurs du secteur tels qu'ONTOWER, CELLNEX ou DELTA ZONING. Cette activité génère un volume très important de comptes-rendus d'intervention qui, jusqu'à présent, étaient saisis dans Kizeo Forms, une solution SaaS facturée par utilisateur.

Deux problèmes justifiaient l'abandon de Kizeo : un coût récurrent qui grandit avec l'effectif itinérant, et surtout une dépendance vis-à-vis d'un prestataire externe sur un outil devenu central à l'activité opérationnelle. Le directeur général a donc décidé d'investir dans le développement d'un outil interne sur mesure, hébergé sous le contrôle de l'entreprise, sans abonnement par utilisateur, et adapté aux usages réels du terrain. C'est cette mission qui m'a été confiée, en collaboration avec mon maître de stage Monir Hamouda, mon tuteur de stage Quentin Foessel et un autre développeur de l'équipe.

Architecture générale de l'application

L'application repose sur le framework Symfony 8 en PHP 8.4, selon une architecture Modèle-Vue-Contrôleur classique enrichie de plusieurs patrons de conception. Le modèle de données s'appuie sur l'ORM Doctrine, qui permet une abstraction vis-à-vis du moteur de base de données — un choix qui s'est révélé décisif puisque l'environnement de développement local utilise PostgreSQL via un conteneur Docker, tandis que la production sur Infomaniak fonctionne sous MariaDB. Trois entités principales structurent le domaine : Site pour le référentiel des installations télécom, Rapport pour les comptes-rendus d'intervention, et Image pour les photos jointes par les techniciens.

Tout au long du projet, l'environnement de développement a été simulé localement grâce à Docker, qui permet d'exécuter une infrastructure serveur complète sur la machine de l'équipe sans passer par un hébergement distant. Un fichier docker-compose.yml orchestre les services nécessaires : un conteneur PostgreSQL pour la base de données, le serveur web Symfony local pour servir l'application, et les volumes assurant la persistance des données entre deux lancements. Cette approche présente plusieurs avantages : tous les développeurs partagent un environnement identique, le projet est immédiatement reproductible sur une nouvelle machine via une seule commande docker-compose up, et la base de données reste isolée du système hôte — ce qui évite les conflits avec d'éventuelles installations PostgreSQL personnelles. Symfony et Docker ont ainsi simulé en local les conditions d'un serveur de production tout au long du développement.

L'abstraction de Doctrine couvre la plupart des requêtes courantes, mais les migrations de schéma de base de données exposent malheureusement les différences entre PostgreSQL et MariaDB : la syntaxe d'altération d'une colonne, la gestion des contraintes ou les fonctions natives diffèrent d'un moteur à l'autre. Pour conserver un dépôt unique fonctionnant aussi bien en local qu'en production, chaque migration sensible a été rendue consciente de la plateforme grâce à un simple test instanceof :

// migrations/VersionXXXXXXXX.php — migration cross-platform public function up(Schema $schema): void { if ($this->platform instanceof PostgreSQLPlatform) { $this->addSql("ALTER TABLE image ALTER COLUMN rapport_id DROP NOT NULL"); $this->addSql("ALTER TABLE image ADD COLUMN uploaded_at TIMESTAMP NOT NULL DEFAULT NOW()"); } else { // MariaDB / MySQL (production Infomaniak) $this->addSql("ALTER TABLE image MODIFY COLUMN rapport_id INT DEFAULT NULL"); $this->addSql("ALTER TABLE image ADD COLUMN uploaded_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); } }

Une attention particulière a été portée à l'extensibilité du système. Les quinze types de rapports n'ont pas été codés en dur sous forme de switch / case mais implémentés selon le patron Strategy, chaque type disposant d'un handler dédié qui implémente une interface commune. Un registre central découvre automatiquement ces handlers grâce à la fonctionnalité de tagged services du conteneur Symfony : pour ajouter un nouveau type de rapport, il suffit d'écrire une classe implémentant RapportHandlerInterface, qui est reconnue et enregistrée sans aucune modification du code existant.

// src/Rapport/RapportHandlerRegistry.php — registre auto-découvert public function __construct( #[AutowireIterator('app.rapport_handler')] iterable $handlers ) { foreach ($handlers as $handler) { $this->handlers[$handler->getType()] = $handler; } } public function getHandler(string $type): RapportHandlerInterface { return $this->handlers[$type] ?? throw new InvalidArgumentException("Type inconnu : $type"); }

Tableau de bord et authentification

L'application est protégée par un formulaire de connexion sécurisé qui constitue le point d'entrée unique. La page de login intègre une protection CSRF, un mécanisme de login throttling qui bloque temporairement l'accès après sept tentatives infructueuses sur une fenêtre de quinze minutes, et un hachage des mots de passe en bcrypt avec un coût de treize itérations. Une fois authentifié, l'utilisateur accède à un tableau de bord qui centralise les actions courantes : création d'un nouveau rapport, consultation des interventions récentes, statistiques globales (nombre total de rapports, volume du mois en cours) et accès au référentiel de sites.

Page de connexion sécurisée
Page de connexion — protection CSRF et throttling
Tableau de bord de l'application
Tableau de bord — accès rapide aux fonctionnalités

Module de gestion des rapports

Le cœur fonctionnel de l'application est le module de gestion des rapports. Chaque intervention donne lieu à la création d'un rapport typé (audit sécurité, travaux CELLNEX, visite technique, déconsignation, campagne ILOQ, etc.), structuré selon les champs et sections définis dans le formulaire Kizeo original. La liste des rapports affiche l'historique des interventions avec un filtrage par type, par site et par date, et chaque ligne donne accès à la fiche détaillée correspondante.

Liste des rapports
Liste des rapports — historique filtrable des interventions

La saisie d'un rapport a été conçue selon une approche mobile-first : les champs sont présentés sous forme de blocs successifs, lisibles et accessibles au pouce, avec des contrôles adaptés à chaque type de donnée (cases à cocher, listes déroulantes, sélecteurs de date, champs texte libres). Le formulaire intègre un module d'upload photographique permettant au technicien soit de joindre des clichés depuis sa galerie, soit de déclencher directement l'appareil photo de son terminal via l'API capture du navigateur — une fonctionnalité particulièrement utile pour documenter en temps réel l'état d'une installation.

Formulaire d'ajout d'un nouveau rapport
Formulaire de saisie — structure modulaire mobile-first

Une fois enregistré, chaque rapport est consultable dans une vue détaillée qui restitue l'ensemble des informations saisies ainsi que les photos annexées, organisées dans une galerie visuelle. Cette vue est conçue pour servir aussi bien aux techniciens souhaitant relire leur intervention qu'aux équipes de bureau chargées du suivi et de la facturation.

Vue détail d'un rapport
Détail d'un rapport — informations et galerie photo
Exemple de rapport d'accès rempli
Rapport d'accès — exemple de type métier spécifique

Référentiel des 42 621 sites télécom

Le second pilier de l'application est le référentiel national des sites. Constitué à partir du fichier Excel maintenu historiquement par THF-ES, il regroupe désormais 42 621 entrées, chacune correspondant à une installation télécom répertoriée. Chaque site est identifié par un code international standardisé (du type FR-01-000364), un éventuel code antérieur à cession, un nom, une adresse complète, une ville, une région, un type de bâtiment et une trentaine de champs complémentaires couvrant les conditions d'accès, les contacts publics et privés, les contraintes horaires, les risques d'agression ou les délais de prévenance.

Page de recherche de la base de données
Référentiel national — 42 621 sites avec recherche paginée

La page de recherche s'appuie sur le bundle KnpPaginator pour une pagination performante (25 résultats par page), avec une barre de recherche libre qui interroge plusieurs champs simultanément (code, nom, ville). La consultation d'une fiche site présente les données structurées en sections lisibles et permet d'exporter la fiche au format PDF pour archivage ou transmission par e-mail.

Fiche détail d'un site
Fiche site — informations structurées
Export PDF d'une fiche site
Export PDF — fiche site mise en page via Dompdf

Import / export CSV du référentiel

La base de données des sites étant amenée à évoluer fréquemment (création de nouveaux sites, mise à jour des contacts, changement des conditions d'accès), il fallait permettre à l'administrateur d'enrichir le référentiel sans passer par une intervention technique. J'ai donc développé en fin de stage une fonctionnalité d'import et d'export CSV directement accessible depuis l'interface.

L'export produit un fichier CSV contenant les 42 621 sites avec l'ensemble de leurs champs, encodé en UTF-8 avec marqueur BOM pour rester compatible avec Microsoft Excel en français, et utilisant le point-virgule comme séparateur (convention française). Pour éviter de saturer la mémoire du serveur sur un export de cette volumétrie, j'ai utilisé le mécanisme de StreamedResponse de Symfony combiné à une lecture par lots de 500 sites depuis la base, ce qui permet de générer et de transmettre le fichier au navigateur progressivement, sans jamais charger l'intégralité du référentiel en mémoire.

// src/Controller/DatabaseController.php — export streamé par lots return new StreamedResponse(function () use ($siteRepository) { $handle = fopen('php://output', 'w'); fwrite($handle, "\xEF\xBB\xBF"); // BOM UTF-8 pour Excel FR fputcsv($handle, $headers, ';'); $offset = 0; do { $sites = $siteRepository->createQueryBuilder('s') ->setFirstResult($offset) ->setMaxResults(500) ->getQuery()->getResult(); foreach ($sites as $site) { fputcsv($handle, $this->rowFor($site), ';'); } $offset += 500; } while (count($sites) === 500); fclose($handle); });

L'import fonctionne selon un mode upsert : chaque ligne du CSV est confrontée au référentiel existant par le code international. Si le site existe déjà, ses champs sont mis à jour avec les nouvelles valeurs non vides — ce qui permet à l'administrateur d'enrichir progressivement la base sans craindre d'écraser des données déjà saisies. Si le code n'est pas reconnu, un nouveau site est créé. L'import gère également les fichiers encodés en Windows-1252 (encodage par défaut de certaines versions d'Excel) et applique une normalisation des en-têtes de colonnes (passage en minuscules, suppression des accents, transformation des espaces) afin de tolérer de légères variations dans les fichiers fournis. Un compte-rendu d'import affiche en temps réel le nombre de sites créés, mis à jour et ignorés.

Modale d'import CSV
Import CSV — modale avec rapport détaillé de l'opération

Assistant conversationnel et génération de PDF

L'assistant conversationnel alimenté par l'API Mistral AI, déjà présenté dans le rapport de lancement, est resté un point fort de l'application. Accessible depuis un bouton flottant présent sur toutes les pages, il permet aux techniciens d'obtenir en langage naturel des informations sur un site (recherche par code, par ville, par caractéristiques), de consulter la météo prévue sur un lieu d'intervention ou d'obtenir de l'aide sur l'utilisation de l'application. Le choix de Mistral, fournisseur français hébergeant ses données en Europe, garantit une conformité RGPD que n'offraient pas les alternatives américaines.

Assistant conversationnel Mistral AI
Chatbot Mistral AI — recherche en langage naturel

La génération de PDF repose sur la bibliothèque Dompdf, qui transforme un gabarit HTML/CSS en document PDF prêt à archiver ou transmettre par e-mail. Chaque rapport peut ainsi être exporté avec son en-tête institutionnel, ses photos et son compte-rendu mis en page. Le PDF est généré à la demande, sans stockage côté serveur, ce qui évite la duplication des données et garantit que le document est toujours synchronisé avec la dernière version saisie.

Mise en production et chaîne d'intégration continue

La dernière phase du stage a consisté à industrialiser la mise en ligne de l'application sur les serveurs Infomaniak, hébergeur retenu pour sa conformité RGPD et ses datacenters basés en Suisse. La chaîne CI/CD a été mise en place via GitHub Actions : chaque push sur la branche main du dépôt déclenche automatiquement un déploiement.

Dépôt GitHub du projet
Dépôt GitHub — branche principale et workflow Actions

Le workflow se connecte au serveur Infomaniak par SSH, récupère la dernière version du code via git pull, installe les dépendances PHP en mode production (composer install --no-dev --optimize-autoloader), compile les asset-maps Symfony, applique les migrations Doctrine en attente, puis purge et reconstruit le cache applicatif. L'ensemble est entièrement automatisé : il n'y a plus d'intervention manuelle sur le serveur de production, ce qui élimine une source d'erreurs et garantit la reproductibilité des déploiements.

# .github/workflows/deploy.yml — pipeline de déploiement Infomaniak on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd ${{ secrets.DEPLOY_PATH }} git pull origin main composer install --no-dev --optimize-autoloader php bin/console asset-map:compile --env=prod php bin/console doctrine:migrations:migrate --no-interaction --env=prod php bin/console cache:clear --env=prod php bin/console cache:warmup --env=prod
Application déployée sur Infomaniak
Application en production sur Infomaniak

Planning du travail réalisé

Sur les deux mois du stage, le travail s'est articulé autour de quatre phases successives, chacune correspondant à un livrable identifié et validé avec mon maître de stage Monir Hamouda et mon tuteur Quentin Foessel. Cette découpe a permis de garder un cap clair tout au long du projet, tout en conservant la souplesse nécessaire pour intégrer au fil du temps les retours des techniciens de terrain.

  1. Phase 1 — Analyse et conception

    Semaines 1 à 2

    Première période consacrée à la compréhension du métier, à l'étude détaillée des quinze formulaires Kizeo existants et aux entretiens avec les équipes terrain et bureau. Mise en place de l'architecture Symfony / MVC, modélisation Doctrine des trois entités principales (Site, Rapport, Image), choix de l'identité visuelle (thème sombre professionnel, responsive mobile-first) et développement d'un premier prototype de tableau de bord. Cette phase s'est conclue par la livraison du rapport de lancement.

  2. Phase 2 — Développement des fonctionnalités cœur

    Semaines 3 à 4

    Implémentation des contrôleurs CRUD pour les rapports et les sites, du module d'upload photo avec capture native et de l'intégration de Dompdf pour la génération des fiches. Import initial des 42 621 sites depuis le fichier Excel via une commande Symfony dédiée, suivi de la mise en place de la pagination KnpPaginator pour rendre cette volumétrie consultable de manière performante. En parallèle, intégration de l'assistant conversationnel Mistral AI et premiers tests utilisateurs sur smartphone via ngrok.

  3. Phase 3 — Handlers métier et mise en production

    Semaines 5 à 6

    Développement progressif des quinze handlers de rapports métier suivant le patron Strategy, mise en place du registre auto-découvert via tagged iterator et industrialisation du déploiement sur Infomaniak via GitHub Actions. Cette phase a été ponctuée par la résolution de plusieurs incompatibilités entre l'environnement de développement local (PostgreSQL, Docker, Linux) et l'environnement de production (MariaDB, hébergement mutualisé) : différences de syntaxe SQL résolues par des migrations sensibles à la plateforme, divergences de version PHP corrigées dans le workflow CI et ajustements de configuration des bundles selon l'environnement.

  4. Phase 4 — Sécurisation et finitions

    Semaines 7 à 8

    Renforcement de la sécurité applicative : mise en place de l'authentification Symfony avec login throttling, ajout des en-têtes HTTP de sécurité via un EventListener dédié, génération d'un APP_SECRET cryptographiquement fort et nettoyage des éventuels éléments sensibles dans le code source. Développement de la fonctionnalité d'import / export CSV permettant à l'administrateur de maintenir le référentiel sans intervention technique. Tests de bout en bout sur l'instance déployée, validation finale avec le maître de stage et rédaction du présent rapport final.


Analyse du travail réalisé

Points forts

La principale réussite du projet réside dans le fait que l'application est aujourd'hui en production et remplit son rôle : les techniciens saisissent leurs rapports depuis le terrain, les équipes de bureau les consultent en PDF et le référentiel de 42 621 sites est interrogeable en temps réel par tous les utilisateurs. L'objectif initial — émanciper THF-ES de son abonnement Kizeo et de la dépendance qui en résultait — est atteint. Le coût récurrent associé à Kizeo est désormais évité, et l'entreprise dispose d'un outil qu'elle maîtrise intégralement, qu'elle peut faire évoluer selon ses besoins, et dont les données restent sous son contrôle.

Sur le plan technique, le choix de Symfony s'est révélé pertinent à plusieurs égards. La robustesse du framework, la qualité de l'écosystème Doctrine et la richesse des bundles ont permis de couvrir les besoins fonctionnels sans introduire de dépendance externe payante. La gestion fine de la configuration par environnement (dev, prod, test) a facilité le passage d'un contexte de développement local à la production en limitant les surprises. La documentation officielle, particulièrement complète, a constitué une ressource précieuse tout au long du projet, et la communauté active autour de Symfony en France garantit une pérennité rassurante pour un outil destiné à être maintenu sur plusieurs années.

L'architecture en handlers auto-découverts via le conteneur de services constitue à mon sens le point d'élégance technique du projet. Elle rend l'ajout d'un nouveau type de rapport quasi-immédiat : il suffit d'implémenter l'interface, et la classe est automatiquement reconnue par le registre sans aucune modification du code existant. Cette approche, conforme au principe ouvert / fermé (open / closed principle), garantit que l'application pourra évoluer sans nécessiter de refonte structurelle.

Enfin, le pipeline de déploiement automatique via GitHub Actions élimine toute manipulation manuelle sur le serveur de production. Cette industrialisation, mise en place progressivement et qui m'a demandé de surmonter plusieurs obstacles techniques, garantit la reproductibilité des mises en ligne, la traçabilité des changements via l'historique Git et la possibilité pour un autre développeur de reprendre le projet sans avoir à découvrir un environnement de production opaque.

Points d'amélioration et actions correctives

Malgré ces réussites, plusieurs axes d'amélioration ont été identifiés au fil du projet et constituent des chantiers à mener pour solidifier l'outil dans la durée.

Tests automatisés

  • Couverture actuelle limitée à cinq fichiers de tests (commande d'import, trois contrôleurs, repository sites)
  • Aucune intégration dans le pipeline de CI : un déploiement peut aboutir alors qu'une régression a été introduite
  • Action : étoffer la suite en ciblant en priorité les handlers métier et la fonctionnalité d'import CSV, puis ajouter une étape vendor/bin/phpunit en début du workflow GitHub Actions pour bloquer tout push qui casserait une fonctionnalité existante

Mode hors-ligne (PWA)

  • L'application est consultable sur mobile mais nécessite une connexion réseau active à chaque action
  • Contrainte réelle pour les techniciens intervenant sur des pylônes en zone rurale ou montagneuse à couverture aléatoire
  • Action : implémenter un service worker qui mette en cache les formulaires et stocke localement les rapports saisis hors-ligne, avec synchronisation différée vers le serveur une fois le réseau retrouvé ; transformer parallèlement l'application en Progressive Web App installable sur le terminal sans passer par les stores

Gestion des rôles

  • Un seul compte administrateur partagé pour cette première version
  • Choix assumé de THF-ES : l'entreprise a délibérément souhaité conserver un fonctionnement mono-compte pour cette première mise en production, afin de simplifier l'adoption interne, l'accompagnement des équipes et la communication des identifiants
  • Évolution prévue : une fois l'usage stabilisé et l'outil pleinement adopté, introduire une séparation en trois rôles (technicien itinérant, employé bureau, administrateur) permettant un cloisonnement fin des permissions, une traçabilité individualisée des saisies et une gestion plus fine des données sensibles

Documentation utilisateur

  • Pas encore de guide utilisateur formalisé à destination des techniciens ou des employés bureau
  • Prise en main actuellement transmise à l'oral lors de sessions de présentation
  • Action : rédiger une documentation concise (PDF de quelques pages ou page dédiée dans l'application) couvrant les parcours principaux : connexion, création d'un rapport, consultation du référentiel, export PDF, et procédure de récupération de mot de passe

Monitoring et journalisation

  • Absence d'outil de supervision en production : aucune alerte automatique en cas d'erreur applicative ou de saturation des ressources
  • Logs Symfony stockés sur le serveur mais non centralisés ni analysés
  • Action : intégrer une solution légère de monitoring (Sentry ou équivalent auto-hébergé), configurer des alertes sur les erreurs 500 et les temps de réponse anormaux, et mettre en place une rotation automatique des fichiers de log pour éviter de saturer le disque

Sauvegardes

  • Aucune procédure de sauvegarde automatique de la base de données n'est encore en place
  • Une perte de données serait critique compte tenu de la volumétrie du référentiel
  • Action : programmer un cron quotidien d'export complet de la base vers un stockage externe (Infomaniak Kdrive ou équivalent), avec une rétention sur trente jours, et documenter la procédure de restauration

Bilan personnel

Ce stage a constitué ma première expérience de développement d'une application complète, de la conception à la mise en production réelle. Avant ce projet, j'avais déjà manipulé Symfony en cours et travaillé sur des exercices isolés, principalement orientés autour de fonctionnalités élémentaires (un CRUD, un système d'authentification basique, une intégration de bibliothèque). Je n'avais en revanche jamais eu à concevoir une architecture de zéro, à prendre des décisions techniques engageantes sur la durée, ni à porter un produit jusqu'à un environnement de production utilisé quotidiennement par de vrais collaborateurs.

Cette dimension a fait évoluer ma manière d'aborder le développement. Chaque choix — celui d'un framework, d'un ORM, d'une bibliothèque PDF, d'un fournisseur d'hébergement, d'une convention de nommage — engage le futur du projet, la facilité de maintenance pour les équipes qui le reprendront, la sécurité des données qui y transiteront et la capacité de l'outil à évoluer face à de nouveaux besoins. Cette prise de conscience du poids des décisions techniques dans un contexte professionnel constitue probablement l'apport le plus structurant du stage, et celui qui modifiera durablement ma manière de coder à l'avenir.

Compétences techniques acquises

Sur le plan strictement technique, j'ai consolidé ma maîtrise de Symfony et de son écosystème : composants Form pour la génération dynamique de formulaires, Security pour l'authentification et les protections CSRF, Doctrine pour la modélisation et les migrations, asset-mapper pour la gestion moderne du front-end, et surtout les mécanismes avancés de dependency injection avec les tagged services et les autowire iterators qui ont rendu possible l'architecture en handlers découverts automatiquement.

J'ai également découvert et pris en main une chaîne complète d'intégration et de déploiement continu avec GitHub Actions et SSH. Cet aspect était globalement absent de ma formation académique, où les projets restent généralement cantonnés à un environnement local. Apprendre à écrire un workflow YAML, à gérer des secrets, à diagnostiquer un échec de déploiement à distance, à comprendre les différences entre l'environnement d'un runner GitHub et celui d'un hébergement mutualisé — toutes ces compétences relèvent d'un savoir-faire opérationnel que seule la confrontation à un vrai projet de production permet d'acquérir.

Le travail simultané sur deux moteurs de base de données (PostgreSQL en local, MariaDB en production) m'a appris à écrire des migrations portables, à reconnaître les pièges classiques des dialectes SQL et à utiliser pleinement l'abstraction qu'offre Doctrine. L'intégration d'une API d'intelligence artificielle dans un contexte professionnel — avec les questions de coût, de latence, de conformité RGPD et de fiabilité que cela soulève — m'a familiarisé avec un domaine devenu incontournable. Enfin, les questions de sécurité applicative (protection CSRF, login throttling, hachage bcrypt, en-têtes HTTP, gestion des secrets de production) ont pris une dimension concrète que les exercices académiques ne permettent pas de saisir.

Compétences humaines et organisationnelles

Sur le plan humain, j'ai appris à dialoguer régulièrement avec des utilisateurs non-techniques — les techniciens itinérants — pour traduire leurs contraintes opérationnelles en fonctionnalités. Cette boucle de retour a été décisive à plusieurs reprises : la taille des boutons sur smartphone, l'ordre des champs dans le formulaire, l'accès rapide à l'appareil photo, la lisibilité du PDF généré — toutes ces décisions d'interface n'auraient jamais été pertinentes sans ces échanges directs avec les utilisateurs réels. Cette pratique d'écoute active et de reformulation est probablement la compétence la moins technique mais la plus transférable que j'aie développée durant le stage.

Le contact quotidien avec mes encadrants Monir Hamouda et Quentin Foessel, ainsi qu'avec l'autre développeur de l'équipe, m'a également familiarisé avec une pratique du travail en équipe — relectures de code, discussions sur les choix d'architecture, résolution conjointe des problèmes complexes, validation mutuelle avant de déployer en production — qui ne peut pas se vivre seul derrière un cours. J'ai notamment appris à défendre mes choix techniques par des arguments, à écouter les contre-propositions et à accepter de revoir ma copie quand un argument plus solide était avancé. Cette posture de dialogue technique ouvert est, je le réalise, une compétence essentielle dans un environnement professionnel.

Défis surmontés

Les difficultés rencontrées ont concerné principalement la phase d'industrialisation. Les premières tentatives de déploiement vers Infomaniak ont échoué sur des incompatibilités de version PHP (le serveur exigeait 8.4 alors que le workflow utilisait initialement 8.2), des problèmes de chargement de bundles selon l'environnement (le bundle de débogage Symfony, présent en mode dev, manquait à l'appel en mode prod sur le runner) ou encore des différences de syntaxe SQL entre PostgreSQL et MariaDB (la fonction NOW(), la syntaxe ALTER COLUMN, la gestion des contraintes NOT NULL).

Chacun de ces obstacles a été l'occasion de comprendre en profondeur des mécanismes que je n'aurais sans doute jamais explorés sans la contrainte d'une production réelle — la différence entre require et require-dev en Composer, le rôle exact des environments Symfony, les subtilités du moteur de migrations Doctrine face à des plateformes hétérogènes. Au final, chacun de ces échecs initiaux a contribué à aboutir à un pipeline fiable et capable de servir de base à des projets futurs.

Conclusion et perspectives

À l'issue de ces deux mois de stage, je ressors avec une vision plus claire et concrète de ce que représente un cycle complet de développement d'application web professionnelle : compréhension du besoin métier, analyse des solutions existantes, conception de l'architecture, développement itératif en lien avec les utilisateurs finaux, mise en production sécurisée, monitoring continu et préparation des évolutions futures. Cette vue d'ensemble, qu'aucun cours ne pourrait restituer en totalité, constitue à mon sens le principal apport de l'expérience.

Cette expérience confirme également mon souhait de poursuivre dans le développement web, avec une appétence particulière pour les sujets d'architecture logicielle, d'industrialisation des déploiements et d'intégration de services externes (API d'IA, fournisseurs de paiement, services tiers). Je remercie THF-ES pour la confiance accordée sur un projet d'une telle envergure, Monir Hamouda pour son accompagnement de maître de stage et Quentin Foessel pour son encadrement de tuteur tout au long de ces deux mois, ainsi que l'ensemble des techniciens et des employés bureau qui ont accepté de partager leurs contraintes opérationnelles pour faire émerger un outil réellement adapté à leurs besoins.