Les bases de données en SPIP

Tout ce que SPIP sait faire avec des bases de données

SPIP peut être vu comme un outil de mise en page dans un format MIME (HTML, RSS, ICS ...) d’extraits de bases de données.
SPIP peut rassembler dans une page des données en provenance de plusieurs bases SQL, accessibles par des serveurs éventuellement différents et distants les uns des autres. SPIP se charge de gérer les différentes connexions et déclarations de tables sans imposer de programmation à ses utilisateurs. Le présent article expose ces manipulations de bases de données.

Installation minimale

Voici d’abord tous les scénarios possibles d’installation de SPIP avec une seule base.

Lors de l’installation de SPIP, celui-ci teste la configuration de PHP et propose, lorsque c’est possible, un choix parmi plusieurs types de serveurs SQL (actuellement MySQL ou SQLite), qui offrent tous les mêmes fonctionnalités. À ce stade, il faut également fournir l’adresse Internet du serveur SQL, un identifiant de connexion à ce serveur et son mot de passe associé. Ces informations sont en général à saisir dans le formulaire d’installation et sont sauvées dans un fichier qui par défaut est config/connect.php. Toutefois, si vous voulez mettre en œuvre la Mutualisation du noyau SPIP, vous pouvez indiquer une ou plusieurs de ces valeurs dans le fichier de configuration mes_options.php. SPIP ne les demandera alors pas, ce qui dispense de les saisir et ne vous oblige pas à les communiquer à ceux qui utiliseront votre installation mutualisée. Voici les noms des constantes PHP à définir pour cela :

_INSTALL_SERVER_DB type du serveur SQL (Mysql ou PG ; casse indifférente)
_INSTALL_HOST_DB nom Internet du serveur SQL (par exemple : localhost)
_INSTALL_USER_DB un nom d’utilisateur du serveur SQL
_INSTALL_PASS_DB son mot de passe

SPIP se connecte alors au serveur choisi, avec les identifiants de connexion. En cas de réussite, il teste si l’utilisateur a le droit de créer des bases, ou seulement le droit de voir celles présentes et d’en choisir une, voire n’a le droit que d’utiliser une base homonyme de son nom d’utilisateur. Vous pouvez également fixer d’avance dans le fichier mes_options.php le nom de la base de données à utiliser, en définissant la constante PHP :

_INSTALL_NAME_DB nom de la base

SPIP poursuit alors l’installation en créant ses tables SQL (ou, en cas de réinstallation, en vérifiant que celles présentes sont utilisables). Ces tables commencent toutes par un préfixe de table (qui vaut par défaut spip_) et peut être indiqué dans mes_options.php de deux manières :

la variable globale $table_prefix
la constante _INSTALL_TABLE_PREFIX

Ce préfixe de table est ce qui permet d’écrire des boucles abrégées dans les squelettes, comme <BOUCLE1(ARTICLES).... alors que le nom SQL de la table est en fait spip_articles.

SPIP demande ensuite de créer le premier utilisateur du site en fournissant un nom et un mot de passe (sans rapport avec ceux du serveur SQL) ou en proposant de déléguer le service d’authentification à un serveur LDAP. Après cette déclaration, la procédure minimale d’installation est terminée, et la page suivante est la page habituelle d’entrée dans l’espace de rédaction, qui demande les identifiants venant d’être saisis.

Compléments d’installation

Voici à présent comment indiquer à SPIP plusieurs bases à exploiter, sous le même serveur ou sous des serveurs différents, et même sur des machines différentes.

Une fois le site installé, choisir le sous-menu maintenance du site dans le menu configuration en haut de l’espace privé. Ce menu fournit une page à trois onglets ; cliquer sur celui de droite, nommé déclarer une autre base. On accède alors à un formulaire quasiment identique au formulaire d’installation : il propose d’indiquer un type de serveur SQL, son adresse Internet, un nom d’utilisateur et son mot de passe. En cas de connexion réussie, SPIP demandera de fournir le nom d’une base, en listant celles présentes s’il en a la possibilité. Si elle existe bien, il créera un fichier de connexion supplémentaire, qui par défaut se trouve dans le répertoire config et porte le nom de la base de données indiquée.

Cela fait, SPIP revient à nouveau à ce formulaire, et liste les fichiers de connexion présents, autrement dit les bases accessibles. SPIP propose donc de déclarer encore une base supplémentaire : il n’y a pas de limitation au nombre de bases déclarables.

L’intérêt de ces déclarations est de pouvoir appliquer la notation des squelettes de mise en pages à ces bases supplémentaires. S’il existe un fichier de connexion nommé B.php, permettant d’interroger une base possédant une table nommée T, alors le squelette <BOUCLE1(B:T) />#TOTAL_BOUCLE<//B1> donnera le nombre de lignes de cette table. De plus, SPIP demande au serveur SQL de lui décrire cette table, ce qui lui permet de connaître ses champs et, éventuellement, sa clé primaire. Si la boucle T a une clé primaire nommée id et un champ nommé nom, alors le squelette : <BOUCLE1(B:T){id}>#NOM</BOUCLE1> donnera le champ nom de l’unique ligne ayant l’id donné par le contexte.

Enfin, il est possible d’appliquer un squelette en demandant que toutes ses boucles utilisent une autre base que celle par défaut, en ajoutant dans l’URL de la page le paramètre connect indiquant le nom de la base. Par exemple http://monsite?connect=autre_site appliquera le squelette sommaire standard du site monsite à la base indiquée par le fichier de connexion config/autre_site.php dans le répertoire d’installation de mon_site.

Il est recommandé de respecter la casse du nom du fichier de connexion, lorsqu’on l’utilise dans une boucle ou comme paramètre de connect : aucune conversion majuscules / minuscules n’est effectuée par SPIP (mais certains systèmes de fichiers le font).

Remarque : L’accès à des bases supplémentaires est exclusivement en lecture ; en particulier, si une base est par exemple un forum (administré par SPIP ou non) il reste impossible de poster dans ce forum autrement qu’à partir de son site d’origine. La levée de cette restriction est à l’étude.

Installations croisées

Les extraits de squelette ci-dessus reposent donc sur l’existence d’un fichier de connexion nommé B.php. Un point important est que le fichier de connexion principal et ceux des bases supplémentaires ont le même format, ce qui permet en particulier à un site SPIP d’utiliser directement le fichier de connexion d’un autre site SPIP pour exploiter ses tables. Une manière de procéder est de copier le fichier connect.php du site B sous le nom B.php dans le répertoire config du site A.

Une manière plus astucieuse, dans le cas de sites partageant une même installation de SPIP, est d’avoir un seul répertoire config pour tous les sites, et d’y nommer le fichier de connexion du site A non pas connect.php mais A.php, de même pour le site B etc. De la sorte, dès qu’un site est installé sous SPIP, il est connu comme base supplémentaire de tous les autres sites partageant cette installation de SPIP, et il verra tous les sites utilisant le même répertoire config que lui comme autant de bases supplémentaires. Pour obtenir cet optimum dans les déclarations implicites, il faut définir soigneusement les constantes _DIR_CONFIG et _FILE_CONNECT_INS. On trouvera plus bas un exemple de mutualisation offrant cette fonctionnalité et quelques autres.

Pour un site installé sur un serveur SQL éloigné, la copie de son fichier de connexion sur le site local peut suffire en théorie. Toutefois beaucoup d’hébergeurs refusent que leurs serveurs SQL soient interrogés par des machines en dehors de leur réseau local. Il faut aussi penser que bien souvent le « nom » indiqué pour le serveur SQL à l’installation est localhost, qui est une adresse relative au serveur HTTP, alors qu’ici il y a nécessité d’une adresse absolue. En bref, SPIP peut opérer dans une telle architecture, mais un minimum de connaissances, voire d’autorisation d’intervention, sur la topographie des sous-réseaux en jeu est pratiquement indispensable.

Les bases supplémentaires sous SPIP

Lorsqu’un fichier de connexion est celui d’un autre site sous SPIP (que ce soit une copie ou l’original accessible par installations croisées), il contient l’indication que ce site est sous SPIP (la globale spip_connect_version y est affectée). Dans ce cas, les squelettes du site principal vont s’appliquer avec un comportement spécial :

-  les boucles avec nom abrégé seront interprétées comme abrégées aussi dans la base supplémentaire ; autrement dit, <BOUCLE1(B:ARTICLES)... (ou <BOUCLE1(ARTICLES)... avec une URL comportant connect=B.) référencera la table spip_articles dans la base B, plus précisément la table prefixearticlesprefixe est celui utilisé par le site B (ce préfixe est indiqué dans le fichier de connexion) ;

-  à l’intérieur d’une boucle, les balises #URL_ (voir Utiliser des URLs personnalisées) utiliseront le type d’URL du site principal, et non du site distant, et l’URL produite référencera le site principal par connect=site_distant ; cette stratégie permet de naviguer dans la base du site distant sans cesser d’utiliser les squelettes du site principal, autrement dit de tester l’apparence que donne ce jeu de squelettes et son type d’URL sur le site distant sans modifier l’installation de celui-ci ou travailler sur une copie.

-  Les raccourcis SPIP des balises #URL qui peuvent figurer dans les champs de la base de données distante sont eux aussi interprétés de cette manière : [->art3681] référencera bien l’article 3681 de la base distante, mais à travers une URL qui fournira la mise en page par les squelettes du site principal.

Ce mode de fonctionnement permet donc de présenter d’autres bases SPIP sans même avoir à écrire des squelettes de mises en page, puisque les noms des tables dans ceux-ci sont les mêmes que ceux du site distant. En revanche, une base qui n’est pas sous SPIP a besoin de squelettes de mises en page nommant explicitement les tables de cette autre base et ses champs. Pour répondre à ce besoin, les administrateurs du site bénéficient d’un traitement spécial : lorsqu’ils donnent à leur navigateur l’URL de leur site suivi de ?page=table:nom_de_la_tablenom_de_la_table est le nom d’une table de la base (exemple : ?page=table:articles), SPIP va automatiquement construire un squelette spécifique à cette table, permettant d’en examiner le contenu avec une grande ergonomie. Le squelette produit est affichable à travers le lien squelette en bas de page. Il est possible alors de le copier à la souris (cliquer en haut de colonne pour cacher la numérotation des lignes) et de l’améliorer en le travaillant sous un éditeur approprié.

À noter qu’avec cette production automatique, SPIP pourrait, à la limite, fonctionner sans aucun squelette prédéfini.

Sauvegardes et Fusions

Avec le sous-menu maintenance du site, SPIP donne accès depuis toujours à deux outils de sauvegarde et restauration de la base de données locale (voir Sauvegarder vos données). Depuis SPIP 2.0, il est possible d’installer une sauvegarde issue d’un vieux site, dans une installation de SPIP de numéro de version supérieur ; toutefois ce cas exige un espace mémoire qui n’est pas toujours disponible, aussi il est toujours conseillé d’essayer de mettre à jour le site d’origine, puis d’en faire la sauvegarde, et enfin de la faire relire par le nouveau site.

D’autre part, jusqu’à la version 1.8, une sauvegarde était totale, et la restauration également. Après quelques essais fondés sur le statut d’administrateur restreint, qui se sont révélés finalement malcommodes, SPIP 2.0 offre une nouvelle fonctionnalité plus harmonieuse de sauvegarde partielle et de restauration par fusion.

Le formulaire de sauvegarde propose de limiter la sauvegarde à une rubrique donnée. Le fichier produit contiendra les articles, sites, brèves et sous rubriques contenu dans la rubrique indiquée, ainsi que les mots-clés et groupes de mots-clés utilisés par toutes ces données. Le nom de la sauvegarde sera par défaut le nom de la rubrique, mais cela peut être changé. La création des fichiers de sauvegarde peut être si longue que le serveur HTTP peut vous déconnecter pour cause d’inactivité apparente. Recharger simplement la page : SPIP retrouvera à quel endroit il en était et poursuivra son travail. Le grand nombre de fichiers que vous pourrez temporairement apercevoir dans un sous-répertoire du répertoire tmp est normal, car lié à l’anticipation de cette situation de reprise après déconnexion.

Symétriquement, le formulaire de restauration propose à présent deux fonctionnalités. La première est l’habituel remplacement de la base courante par la base sauvegardée. La deuxième consiste à considérer le fichier de sauvegarde comme une base incomplète venant s’ajouter à la base déjà installée. Comme il peut y avoir conflit entre la base installée et la base incomplète en ce qui concerne la numérotation de leurs tables (d’articles, de brèves etc), SPIP commence par renuméroter les éléments de la base incomplète en leur affectant des numéros immédiatement supérieurs aux maxima de la base installée. Dans une deuxième passe, SPIP importe effectivement les éléments renumérotés, mais lors de la première passe, il a comparé les éléments à importer avec ceux de la base installée et a ignoré les doublons définis par les règles suivantes :

-  s’il existe dans la base installée un groupe de mots-clés de même nom qu’un groupe de mots-clés à importer, ce groupe est ignoré ;

-  si un mot-clé dont le groupe de mot-clés n’a pas été importé possède un homonyme dans un groupe de mot-clés portant le même nom que son groupe d’origine, ce mot-clé est ignoré ;

-  s’il existe dans la base installée une rubrique de secteur portant même nom qu’une rubrique de secteur à importer, cette rubrique est ignorée ;

-  si une sous-rubrique dont la rubrique parente n’a pas été importée possède un homonyme de même parenté, cette sous-rubrique est ignorée ; il en est de même pour les articles, les brèves et les sites référencés ;

-  s’il existe dans la base installée un document portant même nom qu’un document à importer et qu’ils ont même taille, ce document est ignoré.

Dit de manière plus synthétique, l’opération de fusion est l’union de deux bases, le contenu de la base installée ayant priorité sur la base importée en ce qui concerne les doublons (par exemple, pour deux secteurs de même nom, les champs texte et descriptif de celui déjà installé seront conservés et les autres seront ignorés).

En ce qui concerne les documents joints, ceux-ci seront importés en tant que documents distants, ce qui dispense de recenser et copier la partie du répertoire IMG/ concernée par la sauvegarde partielle. On peut ensuite utiliser, sur chaque document, le bouton de copie locale pour s’affranchir du site d’origine. Si celui-ci a déjà disparu ou possède des restrictions d’accès non contournables par le site récepteur, il faudra installer le répertoire IMG/ originel à une URL accessible, et la donner dans la dernière case de saisie du formulaire d’importation.

On notera la possibilité de rabattre les statuts de valeur publié à la valeur proposé, ce qui permet de garder une politique de publication au cas par cas, malgré cette importation massive.

Un exemple complet

L’installation mutualisée de SPIP ci-dessous permet d’avoir un seul répertoire de configuration (_DIR_CONNECT) et un seul de sauvegardes (_DIR_DUMP). Chaque site peut ainsi donner des aperçus de la base de chacun des autres, et utiliser leurs sauvegardes pour les fusionner avec sa propre base. N’est utilisé aussi qu’un seul répertoire pour le cache de l’aide en ligne (_DIR_AIDE) car SPIP l’importe au coup par coup à partir du serveur spipnet, et un seul répertoire pour les Document Type Definitions que Le validateur XML intégré va chercher sur le site du W3C et autres (_DIR_XML). Les fichiers de droits et de journalisation sont également rassemblés dans seulement deux répertoires (_DIR_CHMOD et _DIR_LOG). Seront donc créés à la racine config/connect, config/chmod, tmp/log, tmp/dump, tmp/xml et tmp/aide. Le premier contiendra A.php pour la connexion à la base A, B.php etc.

if ( preg_match(',/([a-zA-Z0-9_-]*)[/?],',$_SERVER['REQUEST_URI'],$r)) {
  if (is_dir($e = _DIR_RACINE . 'Ajouts/' . $r[1]. '/')) {
    $cookie_prefix = $table_prefix = $r[1];

    define('_SPIP_PATH', 
    _DIR_RACINE. 'Ajouts/' . $table_prefix  . '/dist/:' .
    _DIR_RACINE .'Ajouts/' . $table_prefix  . '/:' .
    _DIR_RACINE .'dist/:' .
    _DIR_RACINE .'dist/javascript/:' .
    _DIR_RESTREINT);

    $pi = $e . _NOM_PERMANENTS_INACCESSIBLES;
    $pa = $e . _NOM_PERMANENTS_ACCESSIBLES;
    $ti = $e . _NOM_TEMPORAIRES_INACCESSIBLES;
    $ta = $e . _NOM_TEMPORAIRES_ACCESSIBLES;

    $pig = _DIR_RACINE . _NOM_PERMANENTS_INACCESSIBLES;
    $tig = _DIR_RACINE . _NOM_TEMPORAIRES_INACCESSIBLES;

    define('_DIR_DUMP', $tig . 'dump/');
    define('_DIR_AIDE', $tig . 'aide/');
    define('_DIR_CACHE_XML', $tig . "xml/");
    define('_DIR_LOG', $tig . 'log/');
    define('_DIR_CONNECT', $pig . 'connect/');
    define('_DIR_CHMOD', $pig . 'chmod/');
    define('_FILE_CONNECT_INS', $table_prefix);
    define('_FILE_CHMOD_INS', $table_prefix);
    define('_FILE_LOG_SUFFIX',
       '_' . $table_prefix . '.log');

    $GLOBALS['test_dirs'] =
      array($pa, $ta, $ti, $pig, $tig,
    _DIR_DUMP, _DIR_LOG, _DIR_CONNECT, _DIR_CHMOD);

    spip_initialisation($pi, $pa, $ti, $ta);
  }
)

Point d’histoire. Dans ses premières versions, SPIP ne donnait accès qu’à certains champs d’une unique base de données (celle qu’il créait à sa première installation). Tout juste était-il possible de simuler plusieurs bases SPIP dans une seule (mais qui s’ignoraient mutuellement) en préfixant le nom des tables de chaque base simulée avec un préfixe spécifique.

SPIP 1.8 et le nouveau compilateur de squelettes, ont ouvert l’accès à tous les champs de toutes les bases accessibles par le serveur HTTP. Mais cette possibilité exigeait d’écrire des fichiers PHP par imitation des fichiers standards, peu intuitifs. De plus, SPIP ne distinguait pas les notions de type de serveurs et de base de données : pour adresser plusieurs bases d’un même serveur, il fallait dupliquer ces fichiers et les adapter. Cette architecture très insatisfaisante explique pourquoi ces fonctionnalités n’ont jamais été documentées, bien que plusieurs extensions de SPIP s’en soient servi.

Auteur Committo, Ergo Sum. Publié le : Mis à jour : 10/07/23

Traductions : català, English, français, Türkçe