Doctrine, Messenger et voters, l'entretien d'un développeur PHP Symfony

Un développeur Symfony passe ses journées dans Doctrine, le conteneur de services et le composant Security. L'entretien vérifie qu'il comprend ce que le framework fait à sa place, ce qui se voit lors d'une montée de version ou devant une page qui ralentit.

Recevoir la fiche complète

Mis à jour le Par l'équipe Delectus5 min de lecture

La fiche Développeur PHP Symfony : technologies, chaîne du poste, une question et la grille d'évaluation

Le développeur PHP Symfony écrit des applications web et des API, souvent avec API Platform, sur une base MySQL, MariaDB ou PostgreSQL. Il manipule les entités Doctrine, les formulaires, le composant Security et Messenger pour les traitements asynchrones avec RabbitMQ ou Redis. Les offres citent PHP 8.3 ou 8.4, Symfony 6.4 ou plus, Docker et une CI GitLab ou GitHub. Le front est en Twig, ou dans une application Angular, React ou Vue séparée.

Une bonne partie des postes concerne du code existant. Symfony publie une version LTS tous les deux ans. La 6.4 cesse de recevoir des corrections de bugs en novembre 2026, la 7.4 reçoit des correctifs de sécurité jusqu'en novembre 2029, et la branche 8 demande PHP 8.4. Des applications en 4.4 ou 5.4 tournent encore et doivent rattraper ce retard. Un candidat qui a mené une montée de version parle des dépréciations, de Rector, de PHPStan et des tests qui ont rendu l'opération possible.

Le profil à surveiller enchaîne les commandes du MakerBundle sans savoir ce que fait l'autowiring ni quand Doctrine envoie ses requêtes. Demandez une requête N+1 corrigée, ou un worker Messenger qui consommait trop de mémoire. Le PDF contient un cas de 20 minutes sur un import de catalogue qui sature la base.

Symfony, Doctrine et les briques autour du framework

Symfony et le conteneur de services

Le framework repose sur un conteneur d'injection de dépendances. Chaque classe déclare ce dont elle a besoin dans son constructeur, et l'autowiring branche les bons services. Le conteneur est compilé une fois, ce qui le rend rapide en production. Demandez au candidat comment il remplace ou décore un service existant.

Doctrine ORM

L'ORM associé à Symfony, en version 3 sur les projets récents. Il suit le modèle de l'unité de travail : les entités modifiées sont écrites en base au flush, pas à chaque setter. Les requêtes N+1 et la mémoire des gros imports viennent souvent de là. Doctrine Migrations versionne le schéma.

API Platform

Le framework d'API construit sur Symfony. Il expose des ressources REST ou GraphQL avec la documentation OpenAPI, la pagination, les filtres et les groupes de sérialisation. Depuis la version 3, les State Providers et State Processors remplacent les data providers et data persisters. Vérifiez que le candidat sait sortir du comportement par défaut.

Symfony Messenger

Le bus de messages. Il place un traitement en file (RabbitMQ, Redis, Doctrine, Amazon SQS) et le fait consommer par des workers. La reprise après échec, le transport des messages en échec et le redémarrage des workers à chaque déploiement reviennent souvent dans les incidents de production.

Security et voters

Le composant Security gère l'authentification par des authenticators (formulaire, JWT, OAuth, SSO) et l'autorisation par les rôles et les voters. Un voter porte une règle métier du type « cet utilisateur peut modifier cette commande ». C'est là qu'on vérifie qu'un client ne voit pas les données d'un autre.

Twig, Form et Symfony UX

Twig est le moteur de templates et échappe le HTML par défaut. Le composant Form gère la saisie, la validation et la protection CSRF. Sur les projets avec un front séparé, ils servent surtout au back-office. Symfony UX (Turbo, Stimulus, Live Components) permet une interface interactive sans framework JavaScript.

PHPUnit, Pest et tests fonctionnels

Les tests unitaires s'écrivent avec PHPUnit ou Pest, les tests fonctionnels avec le WebTestCase de Symfony, qui simule une requête HTTP. Une base de test remise à zéro entre deux tests, avec des fixtures ou Foundry, rend la suite fiable.

PHPStan, Rector et PHP CS Fixer

PHPStan analyse le code sans l'exécuter et détecte les erreurs de type, sur des niveaux de 0 à 10 depuis sa version 2. Rector automatise les montées de version de PHP et de Symfony. PHP CS Fixer applique les règles de style. Tous tournent dans la CI.

PHP-FPM, FrankenPHP, OPcache et Redis

L'application tourne en conteneur avec PHP-FPM derrière Nginx, ou avec FrankenPHP. OPcache et le préchargement accélèrent PHP, Redis sert de cache et de stockage de sessions. Le profiler Symfony et Blackfire montrent où part le temps d'une requête.

Les offres parlent de développeur PHP Symfony, de développeur back-end PHP, ou de développeur full-stack PHP quand un front Angular, React ou Vue s'ajoute. Laravel est l'autre framework PHP courant, avec des réflexes différents : conteneur explicite et Doctrine d'un côté, Eloquent et conventions de l'autre. La certification Symfony, un examen en anglais de 75 questions en 90 minutes, atteste la connaissance du framework. Elle ne remplace pas une discussion sur un projet réel, en particulier une montée de version ou une application à fort trafic.

Les points à vérifier chez un développeur Symfony

  • Conteneur de services et architecture Symfony
  • Doctrine ORM et performance SQL
  • API REST avec API Platform
  • Sécurité, authentification et voters
  • Messenger et traitements asynchrones
  • Tests, qualité et montées de version

Cinq questions Symfony avec la réponse attendue

Chaque question vient avec ce qu'une bonne réponse contient et le signal qui doit vous alerter. Pas besoin d'être technique pour les poser : écoutez si le candidat raconte du vécu.

  1. Question 1 · confirmé

    Une page liste 100 commandes avec le nom du client et le nombre d'articles. Le profiler affiche 201 requêtes. Que corrigez-vous ?

    Une bonne réponseC'est un N+1 : une requête pour la liste, puis une par commande pour le client et une pour les articles, déclenchées par le chargement paresseux dans Twig. Il écrit une requête DQL ou un QueryBuilder avec une jointure et addSelect pour le client, un COUNT groupé ou une sous-requête pour le nombre d'articles, et pagine avec le Paginator de Doctrine dès qu'une collection est jointe. Il vérifie dans le profiler que le nombre de requêtes a chuté.

    Signal d'alertePasser toutes les relations en fetch EAGER, ou mettre la page en cache sans corriger les requêtes.

  2. Question 2 · confirmé

    Un utilisateur peut modifier la facture d'un autre client en changeant l'identifiant dans l'URL. Comment corrigez-vous durablement ?

    Une bonne réponseUn InvoiceVoter qui décide si l'utilisateur connecté peut voir ou modifier cette facture (même client, rôle suffisant), appelé avec #[IsGranted('EDIT', subject: 'invoice')] ou denyAccessUnlessGranted dans chaque action, et par l'option security sur les opérations API Platform. Pour les listes, un filtre dans la requête (extension de requête ou filtre Doctrine) pour ne jamais charger les factures des autres. Il ajoute des tests fonctionnels qui tentent l'accès avec un autre compte.

    Signal d'alerteCacher le bouton dans l'interface, ou ne vérifier que ROLE_USER.

  3. Question 3 · confirmé

    Vous devez ajouter un cache autour d'un service d'appel à une API externe, utilisé dans quarante classes. Comment faites-vous sans toucher à ces classes ?

    Une bonne réponseEn décorant le service : une nouvelle classe implémente la même interface, reçoit le service d'origine et ajoute le cache. Elle est déclarée avec l'attribut #[AsDecorator] ou la clé decorates en YAML. Les quarante classes dépendent de l'interface et reçoivent le décorateur sans aucun changement. Il utilise le composant Cache avec un pool dédié et une durée de vie adaptée.

    Signal d'alerteModifier la classe d'origine, ou créer une sous-classe et changer les quarante injections à la main.

  4. Question 4 · confirmé

    Après un déploiement, les workers Messenger tournent encore sur l'ancien code, et l'un d'eux finit par consommer 2 Go de mémoire. Que mettez-vous en place ?

    Une bonne réponseDes workers gérés par Supervisor ou systemd, lancés avec --memory-limit et --time-limit (ou --limit) pour redémarrer régulièrement, et un messenger:stop-workers à chaque déploiement, une fois le nouveau code en place, pour que chaque worker termine son message et reparte sur la nouvelle version. Il passe des identifiants dans les messages plutôt que des entités, et s'appuie sur les middlewares Doctrine pour vider l'EntityManager et vérifier la connexion entre deux messages.

    Signal d'alerteUn worker lancé à la main dans un screen et jamais redémarré.

  5. Question 5 · confirmé

    Avec API Platform, comment empêchez-vous qu'une ressource User expose le mot de passe haché et que le client modifie son propre rôle ?

    Une bonne réponseDes groupes de sérialisation distincts en lecture et en écriture (normalizationContext et denormalizationContext) qui n'incluent ni le mot de passe ni les rôles, ou mieux des DTO d'entrée et de sortie avec un State Processor qui applique la modification. Les rôles ne se modifient que par une opération réservée aux administrateurs, protégée par l'option security. Un test vérifie qu'aucun champ sensible ne sort dans le JSON.

    Signal d'alerteExposer l'entité telle quelle et masquer les champs côté front.

Recevez la fiche d'entretien complète en PDF

La fiche pour mener l'entretien de bout en bout, prête à imprimer ou à partager avec le manager.

  • 30 questions sur 6 axes, avec la bonne réponse, le signal d'alerte et la relance
  • Le niveau visé pour chaque question
  • Une mise en situation de 20 minutes et ce qu'on attend du candidat
  • La grille d'évaluation de 1 à 4, axe par axe

Questions fréquentes sur le recrutement Symfony

La certification Symfony suffit-elle à valider un candidat ?

Elle montre une connaissance large du framework, vérifiée par un examen de 75 questions en anglais. Elle porte sur une version donnée et sur la théorie, et ne dit rien de la tenue d'une application en production ni de la qualité du code. Prenez-la comme un plus sur le CV, puis vérifiez un projet réel en entretien : une requête N+1 corrigée, un worker stabilisé, une montée de version menée.

Un développeur Laravel peut-il rejoindre un projet Symfony ?

Oui, avec un temps d'adaptation. Le PHP et le SQL ne changent pas, les réflexes si. Eloquent suit le modèle Active Record, Doctrine l'unité de travail, et le conteneur Symfony demande une configuration plus explicite que les façades Laravel. Interrogez la personne sur le flush() de Doctrine et sur l'injection par constructeur. Si elle comprend ces deux points, le reste s'apprend sur le projet.

Que proposer comme test technique pour un développeur Symfony ?

Un petit projet Symfony fourni, avec une page lente à cause d'une requête N+1, une action sans contrôle d'accès et une commande d'import qui manque de mémoire. Demandez de trouver et de corriger un ou deux problèmes en une heure, avec le profiler à disposition, et faites expliquer chaque choix. Vous voyez la méthode de diagnostic et les réflexes de sécurité.

Quelle version de Symfony attendre sur un CV en 2026 ?

Les projets actifs tournent surtout en 6.4 ou 7.4, les deux LTS les plus récentes, ou en 8.x quand l'équipe suit chaque version mineure. Une expérience récente sur 6.4 ou plus montre la pratique des attributs, de l'autowiring moderne et de PHP 8. Un CV qui s'arrête à Symfony 3 ou 4 n'est pas disqualifiant si la personne a suivi PHP depuis. Vérifiez alors qu'elle connaît les attributs, les enums et le typage strict.

Pour structurer vos autres entretiens, consultez aussi nos pages sur les questions d'entretien de recrutement, la méthode de l'entretien structuré et la grille d'évaluation d'entretien.

Les fiches voisines

Toutes les fiches →

Voyez Delectus sur vos propres offres.

Commencez gratuitement. Passez à l'échelle quand vous êtes prêt.

Demander une démo

Votre ATS, connecté à Delectus

  • Workable
  • Teamtailor
  • iCIMS
  • Lever
  • SmartRecruiters
  • Jobvite
  • Greenhouse
  • Pinpoint