Form API Drupal 7 : création de formulaires dans Drupal
Dans les leçons précédentes, nous avons découvert les hooks hook_block_info(), hook_block_view(), hook_menu(), hook_permission() et nous pouvons maintenant créer autant de pages et blocs programmatiquement que nous le souhaitons. Dans cette leçon, nous allons apprendre à utiliser le Form API de Drupal 7 pour créer des formulaires. Nous allons créer un formulaire d’administration des fonctionnalités du module et essayer d’utiliser un maximum de hooks déjà connus afin de renforcer nos compétences.
Pour commencer, nous allons afficher 3 blocs, ce qui ne devrait pas vous poser de problème.
function sitemade_block_info(){ $blocks = array(); // initialisation d’un tableau vide $blocks[1]['info'] = 'Liste des utilisateurs'; // titre du bloc dans l’admin $blocks[2]['info'] = 'Liste des nœuds'; $blocks[3]['info'] = 'Liste des termes'; return $blocks; // retourner la liste des blocs } function sitemade_block_view($delta = ''){ $block = array(); // initialisation d’un tableau bloc vide switch ($delta){ case 1: // même delta que dans hook_block_info() $block['subject'] = 'Utilisateurs'; // titre du bloc $block['content'] = ''; // variable chaîne vide pour contenu $query = db_select('users', 'u') // requête pour sélectionner utilisateurs ->fields('u', array('uid', 'name')) // sélectionner champs ->orderBy('u.uid', 'DESC') // tri décroissant ->range(0, 5) // limiter à 5 utilisateurs ->execute(); // exécuter la requête $users = $query->fetchAll(PDO::FETCH_ASSOC); // fetch en tableau associatif foreach($users as $user){ $block['content'] .=''; // base_path() retourne le chemin racine du site } break; case 2: $block['subject'] = 'Nœuds'; $block['content'] = ''; $query = db_select('node', 'n') ->fields('n', array('nid', 'title')) ->orderBy('n.nid', 'DESC') ->range(0, 10) ->execute(); $nodes = $query->fetchAll(PDO::FETCH_ASSOC); foreach($nodes as $node){ $block['content'] .=''; } break; case 3: $block['subject'] = 'Termes'; $block['content'] = ''; $query = db_select('taxonomy_term_data', 't') ->fields('t', array('tid', 'name')) ->orderBy('t.tid', 'DESC') ->range(0, 10) ->execute(); $terms = $query->fetchAll(PDO::FETCH_ASSOC); foreach($terms as $term){ $block['content'] .=''; } break; } return $block; }
Videz le cache pour que les nouveaux blocs apparaissent dans l’administration. Placez ces blocs dans la barre latérale gauche :
Créons maintenant une page d’administration où nous placerons ensuite le formulaire de gestion de ces trois blocs :
function sitemade_permission(){ return array( 'admin content blocks' => array( 'title' => t('Administration des blocs de contenu'), 'description' => t('Nœuds, Utilisateurs, Termes'), ), ); } function sitemade_menu(){ $items = array(); // initialiser tableau des menus $items['admin/config/content/content_blocks'] = array( 'title' => 'Blocs Utilisateurs, Nœuds, Termes', 'description' => 'Administration des blocs', 'page callback' => '_sitemade_content_blocks', 'access arguments' => array('admin content blocks'), ); return $items; // retourner la liste des pages } function _sitemade_content_blocks(){ $content = 'Lorem ipsum !'; return $content; }
La page est créée, vous devriez voir ce placeholder à l’adresse admin/config/content/content_blocks :
Pensez aussi à attribuer les permissions à l’administrateur pour voir cette page (nous avons défini hook_permission()).
Modifions maintenant nos hooks. Commençons par créer le formulaire d’administration. Que allons-nous administrer dans ces trois blocs ? Je propose le titre du bloc et le nombre d’entités affichées (nœuds, utilisateurs, termes).
Tout d’abord, changeons la propriété 'page callback' de hook_menu :
function sitemade_menu(){ $items = array(); $items['admin/config/content/content_blocks'] = array( 'title' => 'Blocs Utilisateurs, Nœuds, Termes', 'description' => 'Administration des blocs', 'page callback' => 'drupal_get_form', 'page arguments' => array('_sitemade_content_blocks'), 'access arguments' => array('admin content blocks'), ); return $items; }
Description de drupal_get_form() :
drupal_get_form($form_id)
Un wrapper pour drupal_build_form() utilisé quand $form_state n’est pas nécessaire.
Paramètres
$form_id est un identifiant unique pour la fonction constructeur du formulaire. Si une fonction avec ce nom existe, elle est appelée pour construire le formulaire. Les modules qui ont des formulaires similaires peuvent implémenter hook_forms() pour faire correspondre plusieurs $form_id à une fonction constructeur.
Tout autre argument passé à drupal_get_form est transmis à la fonction constructeur. Par exemple, la forme node_edit requiert un objet node passé lors de l’appel du formulaire. Ceci peut être réalisé via hook_form_alter() et hook_FORM_ID_alter() avec le tableau $form_state['build_info']['args'].
Valeur retournée
Un tableau form.
Réécrivons maintenant la fonction _sitemade_content_blocks() pour qu’elle retourne un tableau de formulaire :
function _sitemade_content_blocks(){ $form = array(); // initialiser tableau formulaire $form['nodes-title'] = array( '#type' => 'textfield', '#title' => t('Titre du bloc nœuds'), '#default_value' => variable_get('node_block', ''), '#size' => 60, '#maxlength' => 64, '#description' => t('Titre du bloc pour les Nœuds'), ); $form['node-selected'] = array( '#type' => 'select', '#title' => t('Nombre de nœuds dans le bloc'), '#options' => array( 1 => t('1'), 2 => t('2'), 3 => t('3'), 4 => t('4'), 5 => t('5'), 6 => t('6'), 7 => t('7'), 8 => t('8'), 9 => t('9'), 10 => t('10'), ), '#default_value' => variable_get('node_block_range', 5), '#description' => t('Nombre de nœuds affichés dans le bloc'), ); $form['users-title'] = array( '#type' => 'textfield', '#title' => t('Titre du bloc utilisateurs'), '#default_value' => variable_get('user_block', ''), '#size' => 60, '#maxlength' => 64, '#description' => t('Titre du bloc pour les Utilisateurs'), ); $form['user-selected'] = array( '#type' => 'select', '#title' => t('Nombre d’utilisateurs dans le bloc'), '#options' => array( 1 => t('1'), 2 => t('2'), 3 => t('3'), 4 => t('4'), 5 => t('5'), 6 => t('6'), 7 => t('7'), 8 => t('8'), 9 => t('9'), 10 => t('10'), ), '#default_value' => variable_get('user_block_range', 5), '#description' => t('Nombre d’utilisateurs affichés dans le bloc'), ); $form['terms-title'] = array( '#type' => 'textfield', '#title' => t('Titre du bloc termes'), '#default_value' => variable_get('term_block', ''), '#size' => 60, '#maxlength' => 64, '#description' => t('Titre du bloc pour les termes'), ); $form['term-selected'] = array( '#type' => 'select', '#title' => t('Nombre de termes dans le bloc'), '#options' => array( 1 => t('1'), 2 => t('2'), 3 => t('3'), 4 => t('4'), 5 => t('5'), 6 => t('6'), 7 => t('7'), 8 => t('8'), 9 => t('9'), 10 => t('10'), ), '#default_value' => variable_get('term_block_range', 5), '#description' => t('Nombre de termes affichés dans le bloc'), ); $form['actions'] = array('#type' => 'actions'); // ajouter bouton sauvegarder $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Sauvegarder'), ); return $form; }
'#type' — type d’élément.
'#title' — titre.
'#description' — description.
'#options' — options du menu déroulant.
'#default_value' — valeur par défaut, ici chargée via variable_get.
Le formulaire d’administration doit ressembler à ceci :
Le formulaire est affiché, maintenant nous devons gérer son traitement. Nous utiliserons les hooks hook_formID_validate() et hook_formID_submit() pour valider et traiter le formulaire.
Génération des formulaires
Fonctions disponibles pour gérer et afficher les formulaires HTML dans Drupal.
Drupal utilise ces fonctions pour assurer la compatibilité dans la gestion et l’affichage des formulaires, simplifier le code et réduire la quantité de HTML que les modules doivent générer précisément. La fonction principale est drupal_get_form(), qui génère le HTML du formulaire. Un formulaire peut être créé par programmation sans interaction utilisateur grâce à drupal_form_submit().
drupal_get_form() accepte, traite et affiche automatiquement le HTML généré pour les modules. Voici un exemple d’utilisation de drupal_get_form() et autres fonctions pour générer un formulaire.
<?php $form = drupal_get_form('my_module_example_form'); ... function my_module_example_form($form, &$form_state) { $form['submit'] = array( '#type' => 'submit', '#value' => t('Envoyer'), ); return $form; } function my_module_example_form_validate($form, &$form_state) { // Validation des champs. } function my_module_example_form_submit($form, &$form_state) { // Traitement du formulaire. } ?>
Ou avec quelques arguments supplémentaires :
<?php $extra = "extra"; $form = drupal_get_form('my_module_example_form', $extra); ... function my_module_example_form($form, &$form_state, $extra) { $form['submit'] = array( '#type' => 'submit', '#value' => $extra, ); return $form; } ?>
Écrivons maintenant la fonction de traitement de notre formulaire pour enregistrer les valeurs transmises dans les variables Drupal. Installez le module Devel qui permet d’utiliser la fonction dsm() pour afficher n’importe quel tableau ou objet. Ensuite, ajoutons un hook dans le module :
function sitemade_content_blocks_submit($form, &$form_values){ dsm($form_values); }
Cela affichera les valeurs envoyées par le formulaire :
Nous pouvons maintenant stocker les valeurs dans les variables :
function sitemade_content_blocks_submit($form, &$form_values){ //dsm($form_values); variable_set('node_block', $form_values['values']['nodes-title']); variable_set('user_block', $form_values['values']['users-title']); variable_set('term_block', $form_values['values']['terms-title']); variable_set('node_block_range', $form_values['values']['node-selected']); variable_set('user_block_range', $form_values['values']['user-selected']); variable_set('term_block_range', $form_values['values']['term-selected']); }
Le formulaire est prêt : après envoi, les valeurs sont sauvegardées avec variable_set(), puis chargées comme valeurs par défaut avec variable_get.
Enfin, modifiez hook_block_view() pour que les titres des blocs et le nombre d’éléments affichés soient lus avec variable_get() :
function sitemade_block_view($delta = ''){ $block = array(); // initialisation du tableau bloc switch ($delta){ case 1: $block['subject'] = variable_get('user_block', 'Utilisateurs'); $block['content'] = ''; $query = db_select('users', 'u') ->fields('u', array('uid', 'name')) ->orderBy('u.uid', 'DESC') ->range(0, variable_get('user_block_range', 5)) ->execute(); $users = $query->fetchAll(PDO::FETCH_ASSOC); foreach($users as $user){ $block['content'] .=''; } break; case 2: $block['subject'] = variable_get('node_block', 'Nœuds'); $block['content'] = ''; $query = db_select('node', 'n') ->fields('n', array('nid', 'title')) ->orderBy('n.nid', 'DESC') ->range(0, variable_get('node_block_range', 5)) ->execute(); $nodes = $query->fetchAll(PDO::FETCH_ASSOC); foreach($nodes as $node){ $block['content'] .=''; } break; case 3: $block['subject'] = variable_get('term_block', 'Termes'); $block['content'] = ''; $query = db_select('taxonomy_term_data', 't') ->fields('t', array('tid', 'name')) ->orderBy('t.tid', 'DESC') ->range(0, variable_get('term_block_range', 10)) ->execute(); $terms = $query->fetchAll(PDO::FETCH_ASSOC); foreach($terms as $term){ $block['content'] .=''; } break; } return $block; }
Vous pouvez maintenant voir le résultat sur la page d’accueil. Et n’oubliez pas : « Avant de partir, videz le cache » !