Formation PUB020 : WordPress, 2023 Les données personnalisées WordPress

32.1 Ajouter des tables personnalisées (dbDelta())


Il arrive fréquemment qu'un thème ou une extension ait besoin de ses propres tables.

Les nouvelles tables seront ajoutées à la base de données WordPress afin que le site puisse trouver toutes les données dont il a besoin à partir d'une seule base de données.

En effet, si on avait créé une deuxième base de données, il aurait fallu créer un autre objet pour interroger cette BD. Puisque ceci rendrait le code inutilement complexe, il est préférable d'ajouter vos tables dans la BD originale de votre site WordPress.

dbDelta()

La fonction dbDelta() permet de créer et de mettre à jour ces tables de façon intéressante et efficace.

Attention : il ne faut jamais modifier la structure des tables qui font partie du noyau de WordPress.

Si vous le faites, vous risquez de perdre vos modifications lors de la prochaine mise à jour.

L'idée de base de dbDelta() est la suivante :

  • Si la table demandée n'existe pas, elle est créée selon la structure proposée.
  • Si la table existe, sa structure est comparée avec la structure proposée :
    • Les nouveaux champs sont ajoutés. 
    • Les champs qui diffèrent dans leur type ou dans leur longueur sont ajustés. 
    • Si le nom d'un champ est modifié, un nouveau champ sera créé avec le nouveau nom. L'ancien champ demeurera inchangé. 
    • dbDelta() ne supprimera aucun champ d'une table existante.

La fonction dbDelta() ne fait pas partie du noyau WordPress. Elle est définie dans le fichier wp-admin/includes/upgrade.php. Il faut donc ajouter une instruction require_once() avant son utilisation :

Fichier functions.php ou son sous-fichier tableau-de-bord-tables.php ou fichier de l'extension

require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
$taches_realisees = dbDelta(...);

La valeur de retour de dbDelta() est souvent inutilisée. Pourtant, elle permet de savoir ce qui a été réalisé dans la structure de la table, par exemple :

[gds5_monprefixebd_matable] => Created table gds5_monprefixebd_matable]

ou
[gds5_monprefixebd_matable.nouveauchamp] => Added column gds5_monprefixebd_matable.nouveauchamp

À quel moment les tables personnalisées doivent-elles être créées ?

Le meilleur endroit pour créer les tables personnalisées est lors de l'activation du thème ou de l'extension. Le code sera donc placé à l'un des endroits suivants :

  • Si les tables sont utilisées par un thème, on utilisera le hook after_switch_theme dans le fichier functions.php du thème ou dans un de ses sous-fichiers, par exemple tableau-de-bord-tables.php.

    Fichier functions.php ou son sous-fichier tableau-de-bord-tables.php

    add_action( "after_switch_theme", "monprefixe_creer_tables" );

  • Si les tables sont utilisées par une extension, on utilisera la fonction register_activation_hook() dans la classe de l'extension. Dans l'exemple suivant, l'appel à register_activation_hook() a lieu dans le constructeur de la classe. La méthode creer_tables() est, elle aussi, définie dans la classe de l'extension.

    Fichier de l'extension (PHP)

    register_activation_hook( __FILE__, array( $this, 'creer_tables' ) );

Attention : lors du développement de votre thème ou de votre extension, si vous créez des tables en utilisant after_switch_theme ou register_activation_hook(), vous devrez, dans votre tableau de bord, activer un autre thème puis revenir à votre thème ou encore désactiver puis réactiver l'extension pour que la fonction de rappel soit exécutée.

Ce problème ne se posera pas lorsqu'un autre site utilisera votre thème ou votre extension : dès qu'il l'activera, la fonction de rappel sera exécutée.

Définition de la structure de la table et création avec dbDelta()

Afin d'éviter les conflits avec les extensions ou avec le noyau WordPress, il est important d'ajouter les précautions suivantes :

  • Le nom de la table utilisera le préfixe donné dans le fichier wp-config.php.
  • Afin de rendre le nom de la table unique, on ajoutera, immédiatement après le préfixe remplaçant wp_, un mot relié au thème ou à l'extension qui nécessite cette table.

    Le nom complet sera du genre prefixe_monprefixebd_manouvelletable. Ex : fjdk4_christiane_categories.

    Notez que dans la plupart des cas, ce préfixe sera le même que celui utilisé pour assurer que vos fonctions portent un nom unique. Cependant, ceci n'est pas obligatoire puisqu'il n'y a aucun lien entre les deux.

  • Pour éviter d'alourdir le code inutilement, le nom des champs ne sera pas précédé par le nom du thème ou de l'extension. Par exemple, un champ qui contient une description pourra s'appeler simplement description.

La structure de la table doit être définie à l'aide d'une requête CREATE TABLE.

Afin de vous assurer que la table utilise le bon jeu de caractères et le bon interclassement, il est astucieux de lire ces configurations dans le fichier wp-config.php à l'aide de la méthode $wpdb->get_charset_collate().

Lors de la définition de la requête SQL, il faut absolument respecter les règles suivantes :

  • L'instruction CREATE TABLE, suivie du nom de la table et la parenthèse ouvrante, doit être seule sur sa ligne.
  • Il doit y avoir un espace entre le nom de la table et la parenthèse ouvrante (sans celà, vous obtiendrez une erreur « Table already exists » si vous activez votre thème plusieurs fois).
  • Chaque champ doit être sur sa propre ligne.
  • Il ne doit y avoir aucune ligne blanche dans la définition de la table.
  • Pour identifier la clé primaire, utiliser PRIMARY KEY. Il doit y avoir deux espaces entre PRIMARY KEY et le nom de la clé primaire.
  • Il ne faut pas entourer le nom des champs par des guillemets obliques (en anglais : backticks).

    Exemple à ne pas faire :

    MySQL

    `description` varchar(50)

    Il faut plutôt faire :

    MySQL

    description varchar(50)

Voici un extrait de code pour créer une table personnalisée :

Fichier functions.php ou son sous-fichier tableau-de-bord-tables.php

/**
 * Crée les tables personnalisées pour mon thème enfant.
 * @author Christiane Lagacé <christiane.lagace@hotmail.com>
 *
 * Utilisation : add_action( "after_switch_theme", "monprefixe_creer_tables" );
 */
function monprefixe_creer_tables() {
    global $wpdb;
 
    $charset_collate = $wpdb->get_charset_collate();
 
    $table_matable = $wpdb->prefix . 'monprefixebd_matable';
    $sql = "CREATE TABLE $table_matable (
        id bigint(20) unsigned NOT NULL auto_increment,
        description varchar(50) NOT NULL,
        autrechamp int NULL,
        PRIMARY KEY  (id)
    ) $charset_collate;";
 
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );

    $taches_realisees = dbDelta( $sql );
    monprefixe_log_debug($taches_realisees);

    $erreur_sql = $wpdb->last_error;

    if ('' != $erreur_sql) {
        // réagir en cas de problème
        monprefixe_log_debug("Erreur lors de la création de la table $table_matable.");
        // ...
    }
}

Type des identifiants et des clés étrangères

Si vous allez voir la structure des tables du noyau WordPress, vous remarquerez que les identifiants sont tous de type bigint(20) unsigned. Il serait sage d'employer ce même type pour les identifiants de vos tables personnalisées.

De plus, si une de vos tables contient une clé étrangère liée à un de ces identifiants, vous devrez prendre soin de lui donner à elle aussi le type bigint(20) unsigned.

Insertion des données initiales

Si vous avez besoin d'ajouter des données initiales dans la table, vous pouvez utiliser la fonction $wpdb->insert() après avoir appelé dbDelta()

Dans cet exemple, un seul enregistrement est ajouté. Je vous propose un algorithme pour insérer plusieurs enregistrements sur la fiche « Insérer plusieurs enregistrements dans une table ».

Fichier functions.php ou son sous-fichier tableau-de-bord-tables.php

$reussite = $wpdb->insert(
    $table_matable,
    array(
        'description' => 'blablabla',
        'autrechamp'  => 1
    ),
    array(
        '%s',
        '%d'
    )
);
 
if ( ! $reussite ) {
    // réagir en cas de problème
   monprefixe_log_debug( $wpdb->last_error );
    // ...
}

Attention : tenez compte du fait qu'un thème ou une extension peut être activée et désactivée plusieurs fois. Votre code devra s'assurer que les insertions de données ne soient effectuées qu'une fois...

Une technique intéressante consiste à vérifier si la table visée par dbDelta() contient des enregistrements.

On pourrait aussi choisir de vérifier la présence d'un enregistrement précis.

L'algorighme suivant évitera que les données initiales soient insérées plusieurs fois si le thème ou l'extension était activée et désactivée plusieurs fois.

Fichier functions.php ou son sous-fichier tableau-de-bord-tables.php

$requete = "SELECT COUNT(*) FROM $table_matable";
$presence_donnees = $wpdb->get_var( $requete );
 
if ( is_null( $presence_donnees ) ) {
    $presence_donnees = 0;    // valeur si on ne réussissait pas à retrouver l'info dans la BD
}
 
if ( ! $presence_donnees ) {
    // insertion des données initiales
    // ...
}

Pour plus d'information

« Creating Tables with Plugins ». Codex WordPress. http://codex.wordpress.org/Creating_Tables_with_Plugins

« Chapter 11 Data Types ». MySQL. https://dev.mysql.com/doc/refman/8.0/en/data-types.html

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre