Questions fréquentes
Réponses concrètes sur l’entraînement PHP, Symfony et SQL proposé par Codara.
Général
À qui s’adresse cette plateforme de certification PHP, Symfony et SQL ?
La plateforme s’adresse aux développeurs confirmés qui préparent une certification technique ou souhaitent auditer leur niveau. Les questions couvrent des sujets avancés : typage, performances, internals PHP, architecture Symfony, indexation et optimisation de requêtes SQL. Chaque session produit un score détaillé par thème, ce qui permet de cibler précisément les axes de progression.
Comment se déroule une session de certification en ligne ?
Trois modes sont disponibles : entraînement libre, quiz chronométré et examen blanc. L’examen blanc mélange les trois thèmes, applique un quota de temps par question et fournit à la fin un score global ainsi qu’un détail par compétence. Les corrections détaillées et les explications ne sont dévoilées qu’après la soumission, pour préserver la validité pédagogique de l’évaluation.
Quels sujets sont couverts par les questions ?
Le référentiel est organisé en trois hubs : PHP (typage, gestion de la mémoire, streams, concurrence et bonnes pratiques modernes), Symfony (conteneur de services, cycle de vie HTTP, Doctrine, sécurité et performance) et SQL (index, plans d’exécution, transactions, isolation et fenêtrage). Les questions exigent une compréhension du fonctionnement réel des outils, pas seulement la connaissance de leur syntaxe.
L’entraînement libre et l’examen blanc sont-ils différents ?
Oui. L’entraînement libre permet de choisir un thème, de répondre sans contrainte de temps et d’obtenir une correction immédiate question par question. L’examen blanc reproduit les conditions d’une certification : durée limitée, ordre aléatoire, absence de correction intermédiaire et rapport final structuré par thème. Le mode chronométré se situe entre les deux : thème choisi, temps maîtrisé, correction différée.
PHP
Quand utiliser une enum native plutôt qu’une classe de constantes ?
Une enum native apporte le typage : un paramètre `Status::PENDING` est vérifié à la compilation et ne peut pas recevoir une valeur arbitraire, contrairement à une constante de classe. Elle dispose aussi de méthodes partagées, de valeurs backing pour la persistance et d’un `cases()` itérable. Une classe de constantes reste pertinente pour de simples groupes de valeurs sans sémantique métier ; dès que l’état pilote des comportements, l’enum est plus sûre.
Les propriétés readonly remplacent-elles les value objects immuables ?
Elles en facilitent l’écriture mais n’imposent pas une immuabilité profonde : un tableau ou un objet mutable contenu dans une propriété readonly reste modifiable. Pour un value object, combinez readonly avec des types stricts, des collections immuables et des méthodes qui retournent de nouvelles instances. La promotion de propriétés readonly réduit le boilerplate mais ne dispense pas de penser la copie défensive à la frontière de l’objet.
Comment éviter les pics de mémoire avec de gros volumes de données ?
Remplacez le chargement complet en mémoire par des traitements itératifs : `yield` dans les générateurs, `fgets()` ligne à ligne pour les fichiers, et des curseurs côté base pour les requêtes volumineuses. Mesurez la consommation réelle avec `memory_get_peak_usage()` avant d’optimiser. Libérez explicitement les références dans les boucles longues, car une variable conservée empêche le ramasse-miettes de récupérer l’objet précédent.
Quels réglages OpCache pour une application PHP en production ?
Activez `opcache.enable_cli` uniquement si nécessaire, réglez `opcache.memory_consumption` en fonction du nombre de fichiers et `opcache.max_accelerated_files` au-dessus du nombre réel de scripts. Le revalidation doit rester cohérente avec votre cycle de déploiement : `validate_timestamps=1` en environnement partagé avec un `revalidate_freq` faible, ou timestamps désactivés après un déploiement qui purge le cache. Surveillez `opcache_get_status()` pour détecter un cache saturé qui provoque des recompilations constantes.
À quoi servent WeakReference et WeakMap en pratique ?
`WeakReference` permet d’observer un objet sans prolonger sa durée de vie, par exemple pour une table de cache de métadonnées. `WeakMap` va plus loin : ses clés sont des objets et ne sont pas comptées comme références fortes, ce qui évite les fuites mémoire dans les caches clés par instance. Attention à la sémantique : l’entrée disparaît dès que l’objet-clé est récupéré, donc le code client doit gérer l’absence.
Symfony
Comment diagnostiquer un service Symfony mal configuré ?
Utilisez `debug:container` pour vérifier l’existence, la visibilité et la définition d’un service, et `debug:container <service> --show-arguments` pour inspecter ses dépendances. En cas de boucle de dépendances, cherchez les services construits au chargement plutôt qu’à la demande. Le compilateur signale les erreurs de configuration au moment du dump du conteneur ; privilégiez les diagnostics du conteneur avant d’ajouter des services globaux ou des locators ad hoc.
Quelle est la différence entre un event subscriber et un listener ?
Un listener enregistre une méthode pour un événement précis ; un subscriber déclare lui-même les événements qu’il écoute via `getSubscribedEvents()`. La différence est essentiellement organisationnelle : le subscriber est auto-documenté et se retrouve automatiquement, tandis que le listener est plus discret et adapté aux cas simples. En termes de priorité et d’ordre d’exécution, les deux mécanismes suivent exactement les mêmes règles.
Comment gérer les transactions et la cohérence avec Doctrine ?
Encapsulez les écritures multi-agrégats dans une transaction explicite via `EntityManagerInterface::transactional()`, qui s’occupe du commit et du rollback automatique en cas d’exception. Ne catch pas une exception de persistance pour la masquer : laissez-la remonter pour que le rollback ait lieu. Après une exception, l’EntityManager peut être dans un état incohérent ; dans ce cas, utilisez `reset()` avant de continuer.
Comment sécuriser une route qui accède à une ressource utilisateur ?
Au-delà du contrôle d’authentification, vérifiez toujours la propriété de la ressource. Dans un contrôleur, passez par un voter Symfony dédié à l’action (`can`, `edit`, `delete`) plutôt que de comparer les identifiants dans la route. Pour les opérations API Platform, exprimez la règle dans l’opération et dans un processor qui recharge l’entité depuis le repository. Une ressource chargée directement depuis l’URL sans vérification de propriétaire est une faille d’accès.
Quelle stratégie de cache pour une application Symfony ?
Hiérarchisez : cache HTTP (public, avec invalidation par `Cache-Control` et validation par ETag), puis cache applicatif via `CacheInterface` avec une durée explicite et une clé incluant le contexte (locale, page). Pour les données qui changent peu, utilisez le cache Doctrine de second niveau avec une stratégie d’écriture contrôlée. La règle de base reste la même : ne jamais mettre en cache une réponse dépendante de l’utilisateur authentifié sans clé d’identité.
SQL
Index B-tree, hash, plein texte : comment choisir ?
Le B-tree est le choix par défaut pour les comparaisons d’égalité et de plage. Un index hash n’apporte un gain que sur l’égalité exacte et reste rarement nécessaire en MySQL. Un index FULLTEXT est conçu pour la recherche de mots dans du texte ; il ne remplace pas un index classique pour une recherche par préfixe. Pour les requêtes analytiques, un index composite dont les colonnes respectent l’ordre des prédicats est souvent plus rentable qu’une multiplication d’index simples.
Comment ordonner les colonnes d’un index composite ?
Placez d’abord les colonnes d’égalité (`=`, `IN`), puis les colonnes de plage (`>`, `<`, `BETWEEN`) et enfin les colonnes de tri. Cet ordre maximise la sélectivité de chaque niveau de l’index. Si une colonne de plage apparaît au milieu, les colonnes suivantes ne peuvent plus être utilisées pour la recherche, seulement pour un éventuel tri. Validez toujours avec `EXPLAIN` : l’optimiseur peut choisir un autre index selon les statistiques.
Comment lire un plan d’exécution MySQL efficacement ?
Commencez par la colonne `type` : `ALL` signale un balayage complet, `range` ou `ref` indiquent une utilisation correcte d’un index. Vérifiez ensuite `key`, `rows` et `Extra` : la présence de `Using filesort` ou `Using temporary` trahit un tri ou un regroupement coûteux. Corrigez les écarts entre le nombre estimé de lignes et la réalité en mettant à jour les statistiques. `EXPLAIN ANALYZE` (MySQL 8.0.18+) donne les coûts réels, plus fiables que les estimations.
Quel niveau d’isolation choisir et pourquoi ?
READ COMMITTED est un bon compromis par défaut : chaque lecture voit les données validées et évite les lectures fantômes coûteuses en verrous de plage. SERIALIZABLE garantit une isolation totale mais bloque les plages et réduit la concurrence. REPEATABLE READ, défaut MySQL, donne des instantanés cohérents mais peut masquer des anomalies en lecture. Le choix dépend du compromis entre cohérence et throughput : mesurez les conflits de verrous réels avant de durcir l’isolation.
