# Programmation PHP avec Symfony/Formulaire

* Introduction
* Service
** Contrôleur
** Commande
* Composant
** HttpClient
** Évènement
** Formulaire
** Mailer
** Stimulus
* Bundle
** Twig
** Doctrine
** API
* Introduction
* Service
** Contrôleur
** Commande
* Composant
** HttpClient
** Évènement
** Formulaire
** Mailer
** Stimulus
* Bundle
** Twig
** Doctrine
** API
[ Modifier le sommaire ]

## Principe

Le principe est d'ajouter des champs de formulaire en PHP, qui seront automatiquement convertis en code HTML correspondant.
En effet, en HTML on utilise habituellement la balise <form> pour afficher les champs à remplir par le visiteur. Puis sur validation on récupère leurs valeurs en PHP avec la superglobale $_REQUEST (ou ses composantes $_GET et $_POST). Or ce système ne fonctionne pas en $_POST dans Symfony : si on affiche un tel formulaire et qu'on le valide, $_POST est vide, et l'équivalent Symfony de $_REQUEST, $request->request aussi.
Les formulaires doivent donc nécessairement être préparés en PHP.

## Installation
### Form

Les formulaires présents sont ensuite listables avec :
Et vérifiables individuellement :
Avec le composant maker, on peut créer un formulaire pour chaque entité Doctrine à modifier :

### Validator

Pour ajouter des contrôles sur les champs, il existe un deuxième composant Symfony :

## Contrôleur
### Injection du formulaire dans un Twig

Le second paramètre de createForm est facultatif est sert à préciser des valeurs initiales dans le formulaire qui seront injectées en Twig, mais elles peuvent aussi l'être via le fichier du formulaire dans les paramètres de chaque champ.

### Traitement post-validation

Dans la même méthode du contrôleur qui injecte le formulaire, il faut prévoir le traitement post-validation. Par exemple pour mettre à jour l'entité en base :

## Fichier du formulaire

Dans SF4, l'espace de nom Symfony\Component\Form\Extension\Core\Type propose 35 types de champ, tels que :
* Text
* TextArea
* Email (avec validation en option de la présence d'arrobase ou de domaine)
* Number
* Date
* Choice (menu déroulant)
* Checkbox (cases à cocher et boutons radio)
* Hidden (caché)
* Submit (bouton de validation).

### TextType

Exemple :
Pour préremplir des valeurs dans les champs :
L'attribut "required" peut être interprété par les navigateurs comme un "NotBlank", mais il faut tout de même le compléter avec la contrainte sans quoi un simple retrait du "required" de la page web par la console du navigateur pourrait contourner l'obligation.

### NumberType

Cette classe génère une balise input type="number", qui empêche donc les navigateurs d'écrire des lettres dedans en HTML5.
D'autre part, il y a aussi les problématiques des nombres minimum et maximum, et des séparateurs décimaux et de milliers.
Ex :

### ChoiceType

Il faut injecter le tableau des choix du menu déroulant dans la clé "choices", avec en clé ce qui sera visible dans la liste et en valeur ce qui sera envoyé à la soumission.
Ex :
Dans le cas où une valeur par défaut est définie dans 'data', elle doit appartenir aux valeurs du tableau de "choices", sans quoi elle ne sera pas prise en compte.
{{{1}}}

#### Avec liste modifiable

Si une valeur absente de la liste des choix est envoyée à la soumission, on peut la faire accepter en l'ajoutant à la volée avec :

### EntityType

De plus, en installant Doctrine, il est possible d'ajouter un type de champ "entité" directement relié avec un champ de base de données.
Ex :
En SF4, il n'y avait pas encore les types CheckboxType ou RadioType : il fallait jouer sur deux paramètres de EntityType ainsi :
| Élément | Expanded | Multiple |
| Sélecteur | false | false |
| Sélecteur multiple | false | true |
| Boutons radio | true | false |
| Cases à cocher | true | true |
Exemple :
Pour lui donner une valeur par défaut, il faut lui injecter un objet :

### Sous-formulaire

Utiliser le nom du sous-formulaire comme type :

## Validation
### Validation depuis les entités

Le validateur de formulaire d'entité peut utiliser les annotations des entités. Ex :
En PHP < 8 :
Plusieurs types de données sont déjà définis, comme l'email ou l'URL. Ex :

### Validation depuis les formulaires

Sinon il permet aussi des contrôles plus personnalisés dans les types (qui étendent Symfony\Component\Form\AbstractType). Ex :

### Validation avec un service

Pour valider une entité depuis le service validateur :
NB : le second paramètre est optionnel.
Bien que l'on voit des services correspondant aux contraintes du validateur, on ne peut pas les injecter comme les autres services mais uniquement les utiliser via le validateur général.
Exemple pour valider un email :

## Appel du formulaire Symfony dans la vue

Les fonctions Twig permettant d'ajouter les éléments du formulaire sont :
* form_start
* form_errors
* form_row
* form_widget
* form_label
Pour afficher tout le formulaire, dans l'ordre où les champs ont été définis en PHP :
Pour n'afficher qu'un seul champ :
Les mêmes attributs qu'en PHP peuvent être définis en paramètre. Ex :
Exemple complet :

## Références

* ↑ https://symfony.com/doc/current/components/http_foundation.html
* ↑ https://symfony.com/doc/current/forms.html#form-validation
* ↑ https://symfony.com/doc/current/reference/forms/types/form.html#empty-data
* ↑ https://symfony.com/doc/current/reference/forms/types/choice.html
* ↑ https://github.com/symfony/symfony/issues/42451
* ↑ https://symfony.com/doc/master/reference/forms/types/entity.html
* ↑ https://symfony.com/doc/current/validation.html#string-constraints
* ↑ https://symfony.com/doc/current/validation.html#using-the-validator-service