Drupal 10 : Les formulaires

Comprendre comment créer un formulaire personnalisé

Cet article a été initialement rédigé pour Drupal 8 mais son contenu est toujours d'actualité pour Drupal 9 et Drupal 10.

N'hésitez pas à nous contacter ou à vous inscrire à notre formation «Drupal pour les développeurs et développeuses» pour en savoir plus !

Pour créer un formulaire, il vous faut étendre l’une des trois classes de base fournies par le cœur.
Il y a celle que vous utiliserez probablement le plus qui est
FormBase qui permet tout simplement de créer un formulaire “classique”.
Vient ensuite
ConfirmFormBase qui sert à créer des formulaires de confirmation.
S’ajoute enfin à cela
ConfigFormBase qui permet de faire un formulaire qui va aller exporter ses données dans de la configuration.

Pourquoi s’appuyer sur des classes de base ? Si l’on prend l’exemple de la classe ConfigFormBase, c’est que vous voulez sauver une donnée de façon pérenne dans de la configuration. Pour faire cela proprement, il faut faire appel au service qui gère la configuration (nous verrons plus tard ce que sont les services).
Pour éviter d’avoir à tout (re)faire à la main, des classes de base sont à votre disposition pour cela, chacune apportant sont lot de services et d’accès aux données (utilisateur courant, route, etc) vous évitant ainsi d’écrire beaucoup de code à faible valeur ajoutée.

Voici un exemple de classe d'un formulaire de configuration :

<?php
namespace Drupal\happy_alexandrie\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
 * Configuration form for the grand Alexandrie library.
 */
class AlexandrieConfigForm extends ConfigFormBase {
  /**
   * Defines the form ID.
   *
   * This method replaces the hook_form.
   */
  public function getFormId() {
    return 'alexandrie_config_form';
  }
  /**
   * Indicates the namespace of the exported data for this form.
   *
   * Specific to the config forms, indicates under which name the configuration
   * data should be exported. It will be the filename of the exported data.
   */
  public function getEditableConfigNames() {
    return array(
      'happy_alexandrie.library_config'
    );
  }
  /**
   * Defines the form structure.
   *
   * This is where you will define the content of the form, note that the
   * method takes two arguments as in Drupal 7, the form and form state but
   * the form states is now an object, it must match the FormStateInterface.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // Call the parent implementation to inherit from the save button and
    // form style.
    $form = parent::buildForm($form, $form_state);
    // Add our custom form fields.
    $form['opening_hours'] = array(
      '#type' => 'textarea',
      '#title' => 'Opening hours',
      '#description' => 'Days / hours of the library',
      '#default_value' => $this->config('happy_alexandrie.library_config')->get('opening_hours'),
      '#rows' => 5,
    );
    return $form;
  }
  /**
   * Submit callback.
   *
   * Implements the form logic.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->config('happy_alexandrie.library_config')
      ->set('opening_hours', $form_state->getValue('opening_hours'))
      ->save();
    // Call the parent implementation to inherit from what has been done in it.
    // In our case, display the confirmation message.
    parent::submitForm($form, $form_state);
  }
}

L’identifiant du formulaire est fourni via la méthode getFormId(), le contenu du formulaire est défini dans la méthode buildForm() et le traitement du formulaire une fois soumis est implémenté dans la méthode submitForm(). Il est possible de valider les données via la méthode validateForm().

La variable $form_state est un objet de type FormStateInterface qui permet entre autre d'accéder aux données soumises via la méthode getValue() comme suit :

# NodePreviewForm.php
// Récupération du view mode dans lequel prévisualiser le noeud.
$view_mode = $form_state->getValue('view_mode');

Cette interface contient aussi une méthode setRedirect() pour rediriger utilisateur, une méthode getErrors() pour récupérer les erreurs, une méthode setErrorByName() pour indiquer une erreur sur un champ, une méthode setValue() pour surcharger la valeur d’un champ, etc. Jetez un œil à la définition de l’interface pour voir tout ce qu’il est possible de faire.

La sauvegarde des données se fait via l’API de configuration simple pour être exportées dans les fichiers de configuration YAML.
Cela signifie c’est que c’est à vous d’écrire le code qui exporte vos données (entre autres, parce que c’est aussi à vous de choisir le nom machine de ces données).

Votre commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
Votre adresse servira à afficher un Gravatar et à vous notifier des réponses. Votre commentaire sera anonymisé si ce billet est dépublié pendant plus de 3 mois.
Pour lutter contre le spam notre système enregistre votre adresse IP et votre adresse e-mail si vous la partagez.
Nous vous invitons à consulter notre politique de confidentialité pour comprendre les traitements faits de ces données et comment les rectifier.

À propos de Julien

Co-fondateur - Scrum master & Expert technique

Utilisateur de Drupal depuis 2008, j’ai fait mes armes comme développeur chez Commerce Guys puis me suis mis à encadrer les nouveaux arrivants avant de donner des formations, participer aux avant ventes et accompagner les équipes au passage à Scrum.

Je suis impliqué dans la communauté française de Drupal depuis 2009, j’ai été tour à tour président puis vice-président de l’association Drupal France et francophonie entre 2011 et 2013.