9.8.1. hook_form_alter() : ajouter des fonctions submit et validate à un formulaire existant.
Dans l'une des leçons précédentes, nous avons appris ce que sont les hooks. Dans cette leçon, nous allons travailler avec le hook hook_form_alter()
en pratique et ajouter des fonctionnalités à un formulaire existant.
Des exemples de code sont disponibles sur GitHub :
https://github.com/levmyshkin/drupalbook8
Dans cette leçon, nous commençons à explorer les hooks en pratique, puis nous y reviendrons avec d'autres exemples. Pour l'instant, commençons par hook_form_alter()
.
Pour ajouter un hook dans un module, il faut créer un fichier nommé MODULENAME.module
. Ici, nous créons drupalbook.module
. Ce fichier PHP contiendra nos hooks et fonctions auxiliaires, tandis que pour le reste il est préférable d’utiliser des fichiers et classes dans le dossier src
. Pour l’instant, vous pouvez simplement y ajouter la balise d’ouverture PHP.
Ajoutons maintenant hook_form_alter()
. Si vous utilisez PhpStorm, commencez à taper le nom du hook et l’IDE vous proposera de le compléter automatiquement avec les bons arguments :
Il faut remplacer hook
par le nom de votre module. Drupal détectera ainsi votre code au bon endroit. Voici à quoi doit ressembler la fonction :
/**
* Implémente hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
}
Nous avons vu que $form
contient la structure du formulaire, $form_state
les données d’état, et $form_id
contient l’identifiant du formulaire défini dans la méthode getFormId()
:
Exemple d’identifiant dans la méthode :
function getFormId() {
return 'drupalbook_admin_settings';
}
Ou dans le HTML, on peut voir l’attribut id du formulaire :
Remplacez les tirets -
par des underscores _
. Attention, après une requête AJAX, l’id du formulaire peut être incrémenté (drupalbook-admin-settings-0
, drupalbook-admin-settings-1
, etc.). Il faut utiliser la partie sans le numéro, correspondant à getFormId()
.
Limitons l’exécution à ce formulaire uniquement :
if ($form_id == 'drupalbook_admin_settings') {
// Code spécifique ici.
}
Ajoutons des placeholders aux champs de saisie pour mieux guider l’utilisateur :
if ($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
}
Après modification, videz le cache pour appliquer hook_form_alter()
.
Bien que #attributes
ne soit pas toujours listé officiellement pour les textfields, il fonctionne et permet de définir des attributs HTML (class, placeholder, etc.).
Vous pouvez consulter la classe FormElement
pour voir les valeurs possibles à définir :
Validation
Voyons comment ajouter une fonction de validation personnalisée. Nous allons vérifier que la clé API commence bien par « google », par exemple « google-KEY123a3sa ».
Dans le formulaire, ajoutez la validation :
$form['#validate'][] = 'drupalbook_settings_validate';
La clé #validate
contient un tableau des callbacks de validation qui seront appelés par Drupal.
Créons la fonction dans drupalbook.module
:
/**
* Callback de validation personnalisé.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('La clé API doit commencer par "google".'));
}
}
On utilise l’opérateur strict ===
car strpos()
retourne 0 si la chaîne est trouvée au début, et en PHP 0 == FALSE
est vrai en comparaison faible.
À chaque sauvegarde du formulaire, la validation est appliquée. En cas d’erreur, Drupal affiche un message et empêche la sauvegarde :
Soumission
Après la validation réussie, les fonctions de soumission sont appelées. Nous pouvons en ajouter une pour afficher un message d’aide à l’utilisateur :
$form['#submit'][] = 'drupalbook_settings_submit';
Fonction de soumission :
/**
* Callback de soumission personnalisé.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
\Drupal::messenger()->addStatus(
t(htmlentities('Insérez la clé API dans votre balise <script> : <script src="...key=YOUR_API_KEY"></script>.'))
);
}
On utilise htmlentities()
pour afficher les balises HTML telles quelles, empêchant l’exécution de code malveillant dans les messages.
Le message ne s’affiche que si la validation passe sans erreurs.
Auparavant, la fonction drupal_set_message()
était utilisée, mais elle est maintenant dépréciée au profit du service messenger
orienté objet.
Voici le code complet actuel du fichier drupalbook.module
:
/**
* Implémente hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
$form['#validate'][] = 'drupalbook_settings_validate';
$form['#submit'][] = 'drupalbook_settings_submit';
}
}
/**
* Callback de validation personnalisé.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('La clé API doit commencer par "google".'));
}
}
/**
* Callback de soumission personnalisé.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
\Drupal::messenger()->addStatus(
t(htmlentities('Insérez la clé API dans votre balise <script> : <script src="...key=YOUR_API_KEY"></script>.'))
);
}
Cette leçon conclut notre introduction à l’API Formulaire. Nous reviendrons plus tard sur les fonctions de validation, soumission, ainsi que sur l’utilisation d’AJAX et de form_state
via l’API Formulaire.
Exemples de code disponibles sur GitHub :
https://github.com/levmyshkin/drupalbook8