Déclarer et ajouter des tables dans la base de données

Cet article montre comment ajouter des tables et des boucles à SPIP. Leur procédure d’installation, de désinstallation, et quelques exemples simples de jointure.

Introduction

Quand on développe un plugin SPIP, on a vite besoin d’ajouter une ou plusieurs tables à SPIP. La plupart du temps, elles contiendront les données à afficher aux visiteurs. Mais dans certains cas, elle peuvent aussi servir de "glue" entre plusieurs tables dont les données doivent se recouper. Par exemple, c’est une table externe "joueurs_equipes" qui va venir faire le lien entre la table "joueurs" et "equipes". En SPIP, on appelle ces tables des "tables de jointure".

On a donc deux types de tables :

  • Les tables principales
  • Les tables de jointure

Vous pouvez retrouver la documentation d’une partie de ces tables sur l’article La base de données

La raison de la différenciation de ces tables est l’optimisation de SPIP. En effet, SPIP ne charge que les informations des tables dont il a besoin. Si une boucle ne requiert pas de jointure, alors on ne charge pas les informations des tables de jointure pour cette boucle.

Pour ajouter des tables à SPIP, on passe par deux étapes :

  • Déclaration des tables
  • Installation des tables

Pour réaliser ces deux opérations, on va utiliser 3 pipelines de spip pour déclarer les tables et la balise INSTALL du fichier plugin.xml via la fonction "PREFIXPLUGIN_install" dans le fichier php déclaré dans cette balise

Déclarer les tables

Pour déclarer nos tables à SPIP, on a à notre disposition 3 pipelines.
Pour une documentation complète des points d’entrée, lisez l’article Les points d’entrée (pipelines)

declarer_tables_principales

C’est dans ce pipeline que l’on va définir la structure de nos tables "de contenu".
Tout d’abord, dans le fichier plugin.xml, on déclare le pipeline "declarer_tables_principales" :

La fonction "init_tables_principales" prend un argument qu’on appellera ici "$tables_principales" (peu importe son nom). C’est un tableau qui contient la déclaration des autres tables de SPIP. Le but est d’étendre ce tableau avec la description de nos tables.

Chaque table est décrite via 3 tableaux. Le premier, ’field’, décrit les champs de notre nouvelle table, le deuxième, ’key’, décrit la clé primaire et autres clés de notre nouvelle table et le troisième, ’join’, décrit les champs qui seront candidats à la jointure. Voici un exemple :

Dans notre cas, la table ajoutée sera nommée ’spip_nouvelletable’ dans la base de donnée, elle aura 4 colonnes appelées

  • id_nouvelletable
  • une_colonne
  • une_autre_colonne
  • id_article
    et nous avons déclaré une clé primaire sur id_nouvelletable, une clé simple sur une_autre_colonne, une autre sur id_article et désigné le champ id_article comme candidat à une jointure.
    Vous pouvez retrouver de la documentation sur la base de donnée ici
    Une fonction complète de déclaration de tables principales pourrait ressembler à ça :

Référence : article 4391

declarer_tables_auxiliaires

C’est dans ce pipeline que vont venir les déclarations des tables de jointures.

Tout d’abord, dans le fichier plugin.xml, on déclare le pipeline "declarer_tables_auxiliaires" :

Ensuite, la procédure est exactement la même que pour la déclaration des tables principales. Une fonction complète de déclaration de tables de jointure pourrait ressembler à ça :

Référence : article 4391

On peut bien évidemment déclarer plusieurs tables de jointure dans cette fonction.

declarer_tables_interfaces

A ce stade, SPIP connait les nouvelles tables principales, les nouvelles tables auxiliaires, il sait quelles sont les tables de jointure, mais ne sait pas encore à quelles tables principales elles vont servir. C’est dans le pipeline "declarer_tables_interfaces" que l’on va notamment décrire cela.

Comme dans les pipelines précédents, la fonction accepte une variable, $tables_interfaces par exemple, qui est un tableau de tableaux. Et le but est encore d’étendre ceux-ci avec nos nouvelles entrées.

Comme d’habitude, on déclare le pipeline dans plugin.xml :

et on crée la fonction associée :

par exemple.

Ce pipeline va nous servir à plusieurs niveaux :

Définir le nom des nouvelles boucles

C’est grâce au tableau "$tables_interfaces[’table_des_tables’][]" que nous allons pouvoir faire cela. Voici la notation :

qui donnera une boucle comme celle-ci :

La boucle "NOUVELLEBOUCLE" ira alors chercher les informations dans la table ’spip_nouvelletable’ où ’spip’ sera éventuellement remplacé automatiquement par le bon préfixe de la base de donnée.

Associer les tables principales à leurs tables de jointures [1]

C’est grâce au tableau "$tables_interfaces[’tables_jointures’]" qu’on déclare les tables de jointures à la table principale. On l’utilise comme suit :

Exemple :

Attention, dans la table de jointure, il faut avoir au moins 1 champ de chaque table pour que spip puisse faire le lien entre les deux. Dans notre cas, il devrait y avoir deux champs comme "id_humain" et "id_pomme".

Définir les traitements par défaut sur les champs de nos nouvelles tables

Dans certains cas, certains champs de vos nouvelles tables devront être passés à une ou plusieurs fonctions php avant d’être affichés dans un squelette. Par exemple, le champ texte de la table spip_articles est passé à la fonction propre() pour traduire le code SPIP en html. À la place de devoir écrire "(#MON_CHAMPS" à chaque fois, on peut dire à SPIP de passer le filtre "propre" (ou autre) chaque fois qu’on l’affiche dans un squelette.

Pour ce faire, vous devez déclarer le nom du champ au tableau $interface[’table_des_traitements’][]. Chaque fois que SPIP rencontrera un champ du nom d’une des entrées de ce tableau, la ou les fonctions associées seront appliquées au contenu de ce champ.
Exemple :

Ainsi, à chaque balise "#MON_CHAMPS" sera appliquée la fonction php "ma_fonction". Elle peut être codée dans le fichier "mes_fonctions.php" de spip ou, mieux, dans le fichier php renseigné dans la balise "fonctions" du fichier plugin.xml

Exemple complet :

Dans mes_fonctions.php :

Dans la fonction du pipeline "declarer_tables_interfaces" :

Cet exemple montre un cas où on voudrait que la balise #NOM soit toujours affichée en majuscule.

À déclarer des "exceptions" de tables.

Les exceptions de tables sont des colonnes "virtuelles" d’une table qui font références à d’autres colonnes de cette même table ou à des colonnes d’autres tables, portant le même nom, ou pas.

Exemple :
Nous sommes une asso, on gère pleins de projets, et on voudrait gérer ces projets par SPIP. On va donc créer un plugin gestProj. La particularité, c’est qu’un projet peut en contenir d’autres : Le projet "Organisation d’un festival" contient les projets : "Création site web", "Campagne boomerang", "accueil et logement", "Recherche d’artistes", "Spot TV" et "Recherche de sponsor". Tous ces sous-projets peuvent eux aussi contenir d’autres projets.

On aura donc un table avec un champ "id_projet", mais on aura vite besoin d’un champ "id_projet_parent" pour savoir à quel projet le projet appartient. Pourtant les critères SPIP pour cette fonctionnalité s’appellent "id_parent" et non "id_projet_parent". Eh bien nous allons créer un champ virtuel "id_parent" qui pointera vers "id_projet_parent" comme ceci :

Exemple 2 :
...

Exemple en ligne :
Plugin Agenda

Spécifier les champs "date" des nouvelles tables.

Si on crée une table qui contient des champs date, on peut les déclarer à spip pour accélérer les requêtes sql quand on fait des boucles avec des critère sur ces champs.
On utilisera la notation suivante :

$interface['table_date']['nouvelletable'] = 'champ_date';

exemple :

Voilà à quoi peut ressembler une fonction complète qui va surcharger la pipeline ’declarer_tables_interfaces’ :

Remarques :
On peut voir qu’on nomme la nouvelle boucle "tartes" du même nom que la table sql. Même si SPIP permet de faire des boucles sur des tables non-SPIP, il est toujours bon de les déclarer quand on peut. On augmente ainsi la rapidité des boucles, et donc de SPIP

Installer / Désinstaller les tables sous SPIP 2.0

À ce stade SPIP connait l’organisation de nos nouvelles tables, boucles etc... Nous allons passer maintenant à l’installation et à la désinstallation de celles-ci. Pour ce faire, on va utiliser la balise "install" du fichier plugin.xml

Exemple :

Dans ce fichier, nous aurons besoin des deux fonctions "prefixplugin_upgrade" & "prefixplugin_vider_tables" (trois fonctions, il ne faut pas oublier prefixplugin_install !)

prefixplugin_upgrade

Ce code est exécuté au moment ou vous activez un plugin dans l’espace privé. (a clarifier, visiblement c’est le cas de prefixplugin_install mais pas de prefixplugin_upgrade)

Attention !!, le code sera exécuté à condition que la valeur de dans votre plugin.xml soit plus élevée que celle stockée dans la table spip_meta[’votreplug_base_version’].

C’est le code qui va installer ou mettre à jour les tables de notre plugin. Vous êtes libre d’organiser cette partie comme bon vous semble. Cependant il est pertinent d’utiliser les fonctions sql de SPIP :

  • creer_base()
  • maj_tables($tableau_de_mes_tables)

Concernant la fonction creer_base, il serait plus pertinent de l’utiliser dans prefixplugin_install.

Plus d’infos sur http://programmer.spip.org

De cette manière, votre plugin pourra être utilisé sur tous les types de base de données que SPIP supporte.

Exemple en ligne :
http://zone.spip.org/trac/spip-zone/browser/_plugins_/_stable_/acces_restreint/base/acces_restreint_install.php

prefixplugin_vider_tables

Cette fonction contient le code qui sera exécuté quand l’utilisateur clique sur le petit paquetage du plugin dans l’espace privé. Il sert généralement à vider et/ou supprimer les tables sql. Vous êtes libre d’organiser cette partie comme bon vous semble.

Exemple en ligne :
http://zone.spip.org/trac/spip-zone/browser/_plugins_/_stable_/acces_restreint/base/acces_restreint_install.php

Notes

[1Apparemment l’ordre de déclaration serait important ... à clarifier...