SPIP - Contrib

SPIP - Contrib

[ar] [en] [es] [fr] [it]

81 visiteurs en ce moment

fontsizeup fontsizedown
Accueil du site > Contribs > Documentation > Tutoriaux Multitables & Multibases > Accés SPIP aux tables externes et jointures
[24 commentaires]

Accés SPIP aux tables externes et jointures

jeudi 11 octobre 2007, par Jean Luc Girard

2 votes

Comment accéder avec des boucles SPIP à des tables non SPIP dans un squelette SPIP...

Petit rappel sur SPIP

Depuis la version 1.9 de SPIP il est possible d’accéder avec des boucles SPIP à des tables non SPIP. [1]

Cette possibilité trop méconnue offre des grandes possibilités. SPIP peut devenir le moteur de mise en page de nombreuses applications.

Ces tables externes, quelles sont elles ?

Je vois au moins deux utilisations principales à l’accès aux tables extérieures :

Interroger une application extérieure

Soit pour interroger des tables venant d’une application extérieure pré-existant, dont on veut accéder au contenu à partir d’un squelette SPIP. On peut par exemple utiliser les tables MySQL de n’importe quel script de forum à partir d’un squelette SPIP, pour afficher les derniers messages du forum quelque part à l’intérieur de ce squelette. On pourrait également redéfinir complètement le forum en SPIP et abandonner le script existant...

Interroger des tables que l’on crée

Soit pour interroger des tables créées sur mesure adaptées à un contextes donné, pour lesquelles on veut des champs différents de ceux proposés en standard par SPIP. A la place de surtitre, titre, soustitre, chapo et texte, par exemple, on peut préférer une table « POMMES » proposant les champs : « variete », « couleur », « gout », « origine », « date_degustation » et « indications ».

Par exemple


variete = Belle Fille de Salin
couleur = rouge-jaune
gout = parfum d’amande amère
origine = jura
date_degustation = novembre 2006
indications = à croquer, en jus ou à cuire. N’est pas sensible au gel.

(Saviez vous qu’en 1900, il existait plus de mille variétés de pommes en France ?)

On peut ainsi créer des applications entières utilisant SPIP comme moteur d’affichage.

Certains plugins qui créent leurs propres tables, avec des données extraites dans les squelettes, sont des exemples de mise en oeuvre.

Contraintes

Le traitement entièrement automatique ne requière aucune formalité préalable de la part du créateur de squelette. SPIP a en effet acquis la capacité à découvrir lui-même les particularités de ces tables qui lui sont inconnues et de travailler avec elles.

Il y a quelques contraintes à respecter pour que SPIP interroge les tables inconnues qui lui sont proposées :

- Le nom des tables doit être entièrement en minuscule. Donc pour l’exemple précédent la table « Pommes »devra être renommée « pommes ».

- Ces tables doivent être situées dans la même base de donnée que les tables SPIP. Il est également possible de boucler sur des tables situées dans une autre base de donnée,, et même sur un autre serveur SQL, au prix d’un formalisme spécial et, pour SPIP1.9.2x au prix d’une pré-déclaration en PHP du nom, de l’adresse et du mot de passe de la base. [2]

- euh... c’est tout ?

Pour l’instant, oui. Il y a d’autres contraintes mais c’est sur les jointures.

Interroger directement une table

Il est possible d’interroger une table externe directement via un classique boucle SPIP.

On bénéficie alors à l’intérieur de la boucle
- de critères portant sur tous les champs
- des critères de tris utilisables sur tous les champs
- des critères standards par hasard, inverse, etc...
- de l’accés à tous les champs de la table

Exemple :

<ul>
<BOUCLE_mapomme(POMMES){par date_degustation}{inverse}{couleur=rouge}>
<li>Le #DATE_DEGUSTATION, la #VARIETE a été dégustée</li>
</BOUCLE_mapomme>
</ul>

Note
- en cas d’ambiguité sur le nom d’un champ (par exemple : titre) il faut le préfixer par le "nom de la table" et "point" pour y accéder : {matable.couleur = rouge}

doublons : dans la 1.9.2 on ne peut pas utiliser le critère {doublons}.
A partir de la version 1.9.3., il sera possible d’utiliser le critère {doublons} sur des tables dont un champ sera de type PRIMARY KEY. (A défaut, spip dénonce l’absence d’index sur la table).

Interroger directement deux tables avec jointure

Parfois on a besoin de joindre deux tables pour faire le lien entre leurs éléments. C’est ce qu’on appelle une jointure [3].

Par exemple, j’ai une table « pomme » et une table « gardiens » qui référencent les propriétaires de vergers qui se sont engagés à préserver certaines variétés rustiques de pommes. (C’est un peu ce que promeut l’association Kokopelli, pour la sauvegarde de la diversité potagère).

Cette table contient les champs « nom », « prenom », « adresse », « codepostal » « ville », « telephone », « variete », « quantite ».

Cette table contient des informations du genre Paul Lafarge, habitant La Petite Corcellie, 71190 La Chapelle, dispose de 10 pommiers de variété « Belle Fille de Salin »

C’est le champ « variete » qui fait le lien entre les 2 tables.

<BOUCLE_trouve(pommes gardiens){variete}>
La pomme #VARIETE est gardée par #NOM #PRENOM
</BOUCLE_trouve>

Cas de plus de deux jointures

A noter que ce qui est valable pour 2 tables l’est également pour 3 ou plus. SPIP fait les jointures automatiquement.

Petite complication : à partir de 3 tables de jointures, l’ordre des tables est important et le résultat dépendra de l’ordre. Donc faire des essais sur l’ordre jusqu’à ce que le résultat escompté s’affiche. ( Si quelqu’un sait ou découvre quelle règle doit présider au choix de l’ordre des tables dans la boucle, qu’il le dise ! )

Cela permet de faire des tas de choses.

Nommage des Tables Externes

Recommandation de nommage

Il est trés fortement recommandé de prendre des noms de table au PLURIEL, de même que les tables pour les objets standards de spip sont au pluriel : spip_articles, spip_breves...

Ainsi, préférez FRUITS à FRUIT.

En effet, certains mécanismes standards de spip font des opérations d’accord automatiques, qui devront également pouvoir s’appliquer correctement si vous voulez bénéficier de ces mécanismes pour vos tables externes.

C’est le cas notamment pour la recherche intégrée (voir plus bas).

Si vos tables ne se conforment pas à cette convention, il est parfois utile alors d’utiliser le pipeline ’declarer_tables_objets_surnoms’ -> http://programmer.spip.org/declarer...] mais ces petits noms ne sont pas utilisés dans toutes les situations par le noyau de spip, et donc ce ne sera pas toujours suffisant (la recherche intégrée notamment).

Noms complets et noms résumés

Lorsqu’une table, même externe a le même préfixe qu’une table SPIP, alors il est possible de la référencer sans le préfixe à l’intérieur d’une boucle. On écrira alors son nom en majuscules, sans le préfixe : c’est son nom « logique » tandis que le nom en minuscule et avec le préfixe, c’est le nom « physique ».

Par défaut, le préfixe est « spip_ ». Dans une telle configuration, si on a dans la base de donnee une table « spip_mesfruits » on pourra la référencer directement avec « MESFRUITS » dans une boucle, exemple :

<BOUCLE_ext(MESFRUITS)>...</BOUCLE_ext> ( et dans une jointure idem. )

utilisation de la variable $table_des_tables :

Cette variable sert à SPIP pour le nom des boucles.

Si la table "spip_toto" n’est pas déclarée avec $table_des_tables[’toto’]=’toto’ ; alors il sera impossible de faire <boucle_bb(TOTO) >, mais seulement <boucle_bb(SPIP_TOTO) >, ou <boucle_(spip_toto) >, comme expliqué précédemment, ce qui a l’inconvénient d’être dépendant du préfix de table de SPIP.

En le déclarant, SPIP gère donc le préfixe de table dans les noms des boucles, ce qui permet des plus génériques.

Plugins en rapport

Voir aussi :

- le plugin TableData qui permet de visualiser et modifier dans la partie privée les champs de n’importe quelle table non SPIP.

En faire plus

On peut aussi en vouloir plus de SPIP, et décider d’aller plus loin. Pour cela, on peut utiliser un protocole de déclaration de bases de données externes, de tables externes et de jointures.

Cela permet par exemple d’intégrer les tables externes aux sauvegardes de la base de donnée réalisées par SPIP, ou cela permet de définir des jointures complexes. Attention ces formalismes ne sont pas parfaitement stabilisés, et en les utilisant on s’expose à refaire une partie du boulot lors d’une prochaine évolution de SPIP.

$table_des_jointures :

Sert à SPIP pour relier automatiquement 2 tables, ce qui fait que si on fait une boucle <boucle_bb(TABLE1)>#CHAMP_TABLE_2</boucle_bb>, SPIP fera automatiquement la liaison entre les 2 tables, à condition évidemment qu’elles aient une colonne de nom identique, par exemple "id_rubrique" toutes les deux.

Voir par exemple cette page du Carnet : MultiBase

Recherche dans une table externe

Un pipeline sert à spécifier quels champs sont intégrés dans une recherche. http://programmer.spip.org/recherch...

Ce pipeline peut aussi être utilisé pour les tables externes mais attention : si la table s’appelle "clients_actions" (avec un "s" donc, à la fin) il faut dans le pipeline rechercher_liste_des_champs déclarer les champs SANS LE S !! :

$tables[clients_action][titre]=1;

Notes

[1] La page des nouveautés de SPIP 1.9 annonce cette possibilité

Détection automatique de tables SQL et de jointures

Dans un squelette comportant BOUCLE_a(xxx), la table xxx peut être n’importe quelle table SQL connue du serveur SQL. SPIP demandera alors au serveur SQL de décrire cette table, ce qui lui permettra de compiler le squelette en interprétant toute balise #NOM comme un accès au champ `xxx`.nom s’il existe. Ces champs sont également repérés dans les critères des boucles.

Dans un squelette comportant BOUCLE_a(table table1 ... tablen), les tables supplémentaires seront vues comme des candidates à une jointure, à travers les champs homonymes. Des exemples plus concrets seront donnés dans la documentation.

[2] A partir de SPIP1.9.3, la procédure d’installation de SPIP permettra de déclarer de manière interactive les tables externes auxquelles SPIP pourra se connecter, y compris si elles sont dans une autre base de donnée ou sur un autre serveur. En attendant la doc officielle pour la sortie de la 1.9.3, on pourra consulter la page d’annonce de ces nouveautés

[3] Wikipedia définit ainsi la jointure :

En gestion de base de données relationnelle, une jointure est une combinaison des enregistrements de deux tables disposant de valeurs correspondantes dans un champ determiné de chaque table (souvent ayant le même nom dans les deux).

La table résultante est construite temporairement en fonction des prédicats spécifiés dans la requête. En SQL, ils peuvent être définis par la clause WHERE.

Retour en haut de la page

24 Messages de forum

Voir toute la discussion

Pages 1 | 2 | 3

  • Répondre à ce message

    11 mai 17:47 , par Chag

    Hello,

    Si la table externe s’appelle ma_table (sans s donc), et qu’on la declare comme cela :
    $tables[ma_table][titre]=1 ;

    on va obtenir une erreur de requet sur ma_tables (spip rajoute le s tout seul a priori). Donc, la bonne declaration devient
    $tables[ma_tables][titre]=1 ;

    avec un s cette fois ci que spip retirera lui meme. Il semble également que les tables supplémentaires que l’on souhaite indexer doivent avoir au moins 1 index

    Chag

  • Répondre à ce message

    5 mai 16:17

    Bon, j’ai trouvé la solution à mon problème.

    Le truc, c’est que comme la base à laquelle je voulais acceder était sur une autre machine, et que la machine sur laquelle était hébergée la base spip n’avait pas de base postgresql, le fichier d’install (inc/install.php) ne me proposait pas de choisir entre différents types de bd (mysql versus postgresql).

    Du coup, j’avais écris un fichier de connection à la main en patchant celui généré par spip (nommé connect.php). Et manifestement, il n’était pas tout à fait bon.

    Donc, à grand coup de hache, et de positionnement de variables en dur dans install.php et pg.php, j’ai finalement réussit à lui faire me générer un fichier de connection propre. Et la seule différence était l’absence de la ligne :

    $GLOBALS[’spip_connect_version’] = 0.7 ;

    Une fois enlevé cette instruction de mon fichier de connection, plus de Warning disgracieux. Vous savez quoi, je suis content.

  • Répondre à ce message

    30 avril 09:39 , par erwan

    Non, en fait, la machine sur laquelle tourne le serveur internet est en 8.3.7...

  • Répondre à ce message

    29 avril 17:57 , par erwan

    Bonjour,

    J’interroge depuis une boucle spip une base postgres externe. Tout marche nickel, à part qu’il m’affiche un warning disgracieux : « Warning : pg_query() [function.pg-query] : Query failed : ERROR : relation "spip_meta" does not exist in /spip/ecrire/req/pg.php on line 146 »

    Dans une autre fenêtre, j’ai par ailleurs un « Erreur SQL SELECT valeur FROM spip_meta WHERE nom=’charset_sql_connexion’ 0 »

    J’utilise "spip 2.0.7". Merci à toute bonne ame qui pourrait éclairer ma lanterne.

    Edit : et ma version de posgresql est 7.4.23. Ce pourrait bien être ca le problème...

  • Répondre à ce message

    12 avril 10:02 , par Jean Luc Girard

    J’ai complété l’article avec une note pour permettre la recherche dans des tables externes.

  • Répondre à ce message

    11 février 13:26 , par Lessorg

    Problème résolu.

    En effet, il fallait spécifier le nom de la table (amo_articles) avant la colonne (titre) :

    {par amo_articles.titre}

    Merci beaucoup.

  • Répondre à ce message

    11 février 11:28 , par Jean Luc Girard

    tu ne nous dis pas tout : le message d’erreur dénonce "BOUCLE_articleasso" alors que tes boucles s’appellent "BOUCLE_...amo".

    sinon, essaye {par amo_articles.titre}

  • Répondre à ce message

    10 février 18:52 , par Lessorg

    sisi ça ne marche pas. le probleme vient peut-être d’ailleurs.

       * Erreur(s) dans le squelette
             o Erreur sur le site, {par titre inverse} BOUCLE_articleasso

            <BOUCLE_rubriqueamo(amo_rubriques) {id_rubrique=14} >
                    <h2> #TITRE  </h2>
                    <br> #TEXTE
                    <B_articleamo>
                    <BOUCLE_articleamo(amo_articles) {id_rubrique} {statut='publie'}   {par titre}     {inverse} >
                             #TITRE
                             #TEXTE
                    </BOUCLE_articleamo>
                    </B_articleamo>
            </BOUCLE_rubriqueamo>

    Notons que "par titre" et "inverse" se retrouve dans la même accolade de l’affichage du debug.

    Quand je ne mets pas  {par titre}     {inverse} l’affichage des articles se fait par numéros.

  • Répondre à ce message

    9 février 17:21

    sisi ça marche.
    le probleme doit venir d’ailleurs.

    dans ton précédent message, il manque la parenthese fermante apres le nom de table.
    essaye avec un squelette qui contient juste la boucle (entière)
    et si jamais encore pb, indique nous cette boucle

  • Répondre à ce message

    9 février 16:53 , par Lessorg

    Le problème continue avec la version SPIP 2.0.3 qui affiche "Erreur(s) dans le squelette".

    Quelqu’un a-t-il trouver une solution ?

Pages 1 | 2 | 3

Répondre à cet article

Retour en haut de la page

Ça discute par ici