Mettre en place un CRUD en Drupal 7

  • | Développement
CRUD sur Drupal 7

Pour ajouter des fonctionnalités, il est souvent nécessaire d'ajouter de nouvelles tables métier dans la base de données de Drupal. Pour mettre à jour ces enregistrements on aura besoin d'ajouter un CRUD (Create, Read, Update, Delete) à l'administration du site. 

Au préalable on aura créé une table via l'installation d'un module.

Au programme : 

  1. Créer une liste d'entités
  2. Créer un formulaire pour créer ou modifier une entité
  3. Créer un lien pour supprimer une entité
     

1. Comment créer une liste d'entités pour notre CRUD?

Pour créer une liste dans l'admin de Drupal, on va commencer par implémenter hook_menu dans le fichier mon_module.module pour avoir un lien "admin/mon_module/list" qui pointe vers le callback "mon_module_list" qui se trouve dans le fichier "mon_module.admin.inc".

/**
 * Implements hook_menu().
 */
function mon_module_menu()
{
  $items = array();

  $items['admin/mon_module/list'] = array(
    'title' => 'Liste des entités',
    'description' => 'Voici la liste de mes entités.',
    'page callback' => 'mon_module_list',
    'page arguments' => array('_filter_list_form'),
    'access arguments' => array('administrer site configuration'),
    'file' => 'mon_module.admin.inc',
  );

  return $items;
}

 

Ensuite dans le fichier mon_module.admin.inc, on ajoute notre fonction mon_module_list.

/**
 * Form builder
 */
function mon_module_list($form_state) {

    $form = array();

    $form['search'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#title' => 'Filtrer les résultats',
      '#attributes' => array('class' => array('container-inline')),
    );

    // Adds filter form to the build array.
    $form_search = drupal_get_form('password_filter_form');
    $form['search']['form'] = $form_search;

    // Build the sortable table header.
    // Add field to sort table
    $header = array(
        array('data' => t('id'), 'field' => 'id'),
        array('data' => t('node_id'), 'field' => 'node_id'),
        array('data' => t('title'), 'field' => 'title'),
        array('data' => t('password')),
        array('data' => t('user_id'), 'field' => 'user_id'),
        array('data' => t('mail'), 'field' => 'mail'),
        array('data' => t('Updated'), 'field' => 'changed', 'sort' => 'desc'),
        array('data' => t('Actions'))
    );

    //Build the rows.
    $options = array();

    $query = db_select('mon_module_password', 'mmp')->extend('PagerDefault');
    $query->fields('mmp', array('id', 'node_id', 'password', 'user_id', 'changed'));
    $query->join('users', 'u', 'u.uid = mmp.user_id');
    $query->fields('u', array('mail'));
    $query->join('node', 'n', 'n.nid = mmp.node_id');
    $query->fields('n', array('title'));
    $query->limit(50);
    $query->extend('TableSort')->orderByHeader($header);

    if(isset($_SESSION['form_values']['mail'])) {
      $query->condition('u.mail', '%' . db_like($_SESSION['form_values']['mail']) . '%', 'LIKE');
    }
    if(isset($_SESSION['form_values']['password'])) {
      $query->condition('mmp.password', '%' . db_like($_SESSION['form_values']['password']) . '%', 'LIKE');
    }
    if(isset($_SESSION['form_values']['node_id'])) {
      $query->condition('mmp.node_id', $_SESSION['form_values']['node_id'], '=');
    }

    $result = $query->execute();
    
    foreach ($result as $row) {
    
        $option = array();
        $option[] = array('data' => $row->id);
        $option[] = array('data' => $row->node_id);
        $option[] = array('data' => l($row->title, 'node/'. $row->node_id.'/edit'));
        $option[] = array('data' => $row->password);
        $option[] = array('data' => $row->user_id);
        $option[] = array('data' => l($row->mail, 'user/'. $row->user_id .'/edit'));
        $option[] = array('data' => (!empty($row->changed) ? date('d/m/Y H:i:s', $row->changed) : ''));
        $option[] = array('data' => array('#type' => 'link', '#title' => t('edit'), '#href' => "admin/mon_module/$row->id/edit"));
        $options[] = $option;
    }

    //Build the tableselect.
    $form['table'] = array(
        '#type'         => 'tableselect',
        '#header'       => $header,
        '#options'      => $options,
        '#empty'        => t('Aucun enregistrement.'),
        '#sticky'       => TRUE,
        '#attributes'   => array(),
    );

    $form['pager'] = array('#markup' => theme('pager'));

    /* Using foreach: */
    foreach( $options as $key => $value )
    {
        $form['table'][$key]['#disabled'] = true;
    }

    return $form;
}

 

Plusieurs choses importantes dans cette partie de code : 

  • j'ai ajouté un $form['search'] pour avoir une partie en haut de la liste pour filtrer les résultats. Le formulaire qui s'affiche ici est appelé via un drupal_get_form(password_filter_form)
  • dans le $header, le fait d'ajouter un field ajoute un lien pour trier une colonne de la liste. Il faut mettre le nom de la colonne en base de données. On peut également spécifier un tri par défaut en ajoutant un sort (voir la colonne "Updated").
  • dans la requête les conditions sont liées aux filtres
  • dans l'affichage des résultats je prépare de suite le lien pour updater un enregistrement.
  • quelques infos supplémentaires sur la fonction tableselect

 

Code pour filtrer les résultats : 

/**
 * Implements hook_form().
 */
function password_filter_form($form, &$form_state) {

    // ajout d'un css pour afficher proprement les filtres
    drupal_add_css(drupal_get_path('module', 'mon_module') . '/css/admin.css', array('weight' => CSS_THEME));

    // Sets the values that are stored in session as default.
    $storage = (isset($_SESSION['form_values']) ? $_SESSION['form_values'] : 0);
    $selected_email = isset($storage['mail']) ? $storage['mail'] : NULL;
    $selected_password = isset($storage['password']) ? $storage['password'] : NULL;
    $selected_node_id = isset($storage['node_id']) ? $storage['node_id'] : NULL;

    $downloads = get_all_download_content_type();
    $all_download_titles = array();
    foreach($downloads as $download){
      $all_download_titles[$download->nid] = $download->title;
    }

    $form['node_id'] = array(
        '#title' => 'Par download',
        '#type' => 'select',
        '#options' => $all_download_titles,
        '#default_value' => $selected_node_id,
    );

    $form['mail'] = array(
        '#title' => 'Par email',
        '#type' => 'textfield',
        '#default_value' => $selected_email,
        '#size' => '30',
    );
    $form['password'] = array(
        '#title' => 'Par mot de passe',
        '#type' => 'textfield',
        '#default_value' => $selected_password,
        '#size' => '30',
    );

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Filter'),
    );

    $form['reset'] = array(
        '#type' => 'submit',
        '#value' => t('Reset'),
        '#weight' => 30,
        '#submit' => array('password_reset'),
    );

    return $form;
}

 

A ce niveau on obtient la liste suivante : 

Liste du CRUD en Drupal 7

 

2. Ajouter un formulaire pour créer ou modifier une entité

Ci-dessus on a ajouté un lien pour éditer un enregistrement, voyons donc comment mettre en place ce formulaire?

Dans le fichier "mon_module.admin.inc", on ajoute le menu d'édition et également d'ajout de l'entité : 

  $items['admin/mon_module/%/edit'] = array(
    'title' => 'Modifier une entité',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mon_module_content_type_edit_form', 2),
    'access arguments' => array('administrer site configuration'),
    'file' => 'mon_module.admin.inc',
  );

  $items['admin/mon_module/add'] = array(
    'title' => 'Ajouter une entité',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mon_module_content_type_edit_form'),
    'access arguments' => array('administrer site configuration'),
    'file' => 'mon_module.admin.inc',
    'type' => MENU_LOCAL_ACTION,
  );

 

Puis on crée le formulaire d'édition de l'entité : 

/**
* Retourne le formulaire d'édition d'une entité
*/
function mon_module_content_type_edit_form($form, &$form_state, $download_id = null){

    $query = db_select('download_password', 'dp');
    $query->fields('dp', array('id', 'node_id', 'password', 'user_id', 'changed'));
    $query->condition('dp.id', $download_id, '=');

    $download_entity = $query->execute()->fetch();

    $downloads = get_all_download_content_type();
    $all_download_titles = array();
    foreach($downloads as $download){
        $all_download_titles[$download->nid] = $download->title;
    }

    $form['download_content_type'] = array(
        '#title' => 'Accès sur la publication',
        '#type' => 'select',
        '#default_value' => '',
        '#disabled' => (!empty($download_id) ? true : false),
        '#options' => $all_download_titles,
    );

    $form['download_id'] = array(
        '#title' => 'Accès sur la publication',
        '#type' => 'hidden',
        '#value' => $download_id,
    );

    $form['download_password'] = array(
        '#title' => 'Password',
        '#type' => 'textfield',
        '#disabled' => (!empty($download_id) ? true : false),
        '#default_value' => $download_entity->password,
    );

    $form['download_mail'] = array(
        '#title' => 'Courriel',
        '#type' => 'textfield',
        '#default_value' => get_mail_by_user_id($download_entity->user_id),
    );

    $form['edit'] = array(
        '#value' => 'Enregistrer',
        '#type' => 'submit',
        '#name' => 'edit_abonnement',
    );

    $form['reset'] = array(
        '#type' => 'submit',
        '#value' => t('Cancel'),
        '#weight' => 30,
        '#submit' => array('download_reset'),
    );

    return $form;
}

 

Le code du bouton reset : 

/*
 * Bouton annuler sur le formulaire de modification d'un accès
 */
function download_reset() {
    drupal_set_message('Modification annulée');
    drupal_goto('admin/mon_module/list');
}

 

Le traitement du formulaire : 

/**
* Implements hook_submit
* Récupère et met à jour les droits/abonnement
*/
function mon_module_content_type_edit_form_submit($form, &$form_state){

        // update
        if(!empty($form_state['values']['download_id'])) {

                $user = get_user_id_by_mail($form_state['values']['download_mail']);
                if(!empty($user) && $user != 0) {
                    update_download_files_access_by_id(
                        $form_state['values']['download_id'],
                        $user
                    );
                    drupal_set_message('L\'enregistrement a bien été modifié');
                }
                else {
                    drupal_set_message('Cet utilisateur n\'a pas de compte sur le site, il ne peut pas être associé.', 'error');
                }

        }
        //insert
        else {

                 insert_download_files_access_by_id(
                     $form_state['values']['download_content_type'],
                     $form_state['values']['download_password'],
                     get_user_id_by_mail($form_state['values']['download_mail'])
                 );
                 drupal_set_message('Le nouvel accès a bien été créé');
        }

        drupal_goto('admin/mon_module/list');

}

 

 

3. Créer un lien pour supprimer une entité

De la même façon on ajoute un menu au fichier .

$items['admin/mon_module/%/delete'] = array(
     'title' => 'Supprimer une entité',
     'description' => 'Description',
     'page callback' => 'delete_entity',
     'page argument' => array(2),
     'access arguments' => array('administrer site configuration'),
);

 

Et on ajoute la fonction de callback pour supprimer un élément : 

function delete_entity() {

    $id = arg(2);

    $num_updated = db_delete('mon_module_password')
        ->condition('id', $id, '=')
         ->execute();

    drupal_set_message(t('Enregistrement supprimé!'));

    drupal_goto("admin/mon_module/list");

}

 

Et on crée le lien de suppression au même endroit que celui pour la modification ci dessus.

 

Quelques liens pour continuer sur le sujet avec un autre exemple de CRUD en D7 et le même exercice de CRUD en D8.

 

 

L'auteur de cet article
Julien Krier
Responsable Digital, ayant occupé différents postes en informatique depuis 2001, Julien Krier a travaillé sur de multiples plateformes, sites de contenu ou e-commerce à fort trafic. Il est spécialisé dans les technologies web sur les CMS comme Drupal 7 ou Drupal 8 et les Framework Php comme Symfony 5.
Cet article vous a aidé?
Average: 5 (1 vote)
Partagez cet article
Articles sur le même sujet
hook_help() : créer une page d'aide pour un module en Drupal 8Pour développer de bons modules pérennes, il est important d'avoir des informations ou de la documentation sur le fonctionnement du module ou son installation. Pour enregistrer ces informations on implémente le hook_help().
Patcher un module de DrupalIl peut arriver que sur une mise à jour par exemple on se retrouve avec un bug sur un module. Des patchs peuvent alors corriger le problème.
Comment créer un service dans Drupal 8Quand on développe sur Drupal 8, on passe quasiment obligatoirement par la case service. Qu'est ce qu'un service et comment le configurer? C'est par ici!