Terrain 9 — Formulaires & validation
🔍 Renfort : Partie 9.
1. FormType de base ⭐⭐
🕹️ Mission : un ProviderType avec name (texte) et active (case), + bouton.
✅ Solution
$builder
->add('name', TextType::class)
->add('active', CheckboxType::class, ['required' => false])
->add('submit', SubmitType::class);2. Traiter la soumission ⭐⭐
🕹️ Mission : la condition standard pour traiter un formulaire.
✅ Solution
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { /* ... */ }3. Champ enum ⭐⭐
🕹️ Mission : un select à partir de BookingStatus.
✅ Solution
->add('status', EnumType::class, ['class' => BookingStatus::class])4. Contraintes de base ⭐⭐
🕹️ Mission : sur un DTO, email requis+valide, plainPassword ≥ 8.
✅ Solution
#[Assert\NotBlank] #[Assert\Email] public string $email = '';
#[Assert\NotBlank] #[Assert\Length(min: 8)] public string $plainPassword = '';5. DTO plutôt qu’entité ⭐⭐⭐
🕹️ Mission : pour un formulaire d’inscription exposant email/password/roles, pourquoi un DTO ?
✅ Solution
Éviter le mass assignment : lier à l’entité User laisserait modifier roles (élévation de privilèges). Un DTO cadre exactement les champs autorisés ; le service assigne les rôles côté serveur.
6. Unicité ⭐⭐⭐
🕹️ Mission : garantir un email unique. Une contrainte suffit-elle ?
✅ Solution
Non : #[UniqueEntity(fields: ['email'])] (message propre) + unique: true sur la colonne (index unique, garde-fou contre les courses).
7. Contrainte métier ⭐⭐⭐⭐
🕹️ Mission : interdire une réservation sur un créneau complet. Standard ou custom ?
✅ Solution
Custom : Constraint + ConstraintValidator injectable (reçoit SlotAvailabilityChecker), posée sur le DTO. Réutilisée par le formulaire et l’API.
8. Token CSRF manuel ⭐⭐⭐
🕹️ Mission : un formulaire de suppression rendu à la main est toujours invalide. Que manque-t-il ?
✅ Solution
form_rest(form) (rend le token CSRF caché) ; ou, pour un <form> à la main, un csrf_token(...) + isCsrfTokenValid() côté contrôleur.
9. CollectionType ⭐⭐⭐⭐
🕹️ Mission : des sous-formulaires Slot répétés ne persistent pas. Quelle option ?
✅ Solution
by_reference: false (pour appeler addSlot/removeSlot qui synchronisent la relation).
10. Upload sécurisé ⭐⭐⭐⭐
🕹️ Mission : trois règles de sécurité pour un upload de logo.
✅ Solution
Valider le MIME réel (#[Assert\Image], allowlist), régénérer un nom sûr/unique (jamais le nom client), stocker dans un emplacement non exécutable (ou S3).
Terrain suivant : Sécurité.