Notes sur les jointures entre tables

Ceci est une « contribution pédagogique », qui montre par l’exemple comment développer une nouvelle fonctionnalité pour SPIP.

Après avoir cherché à divers endroits des infos sur les jointures entre tables dans SPIP, je réunis ici quelques notes en vrac...

Critères : jointures automatiques

Comme l’explique bien l’article de Programmer

Lorsque dans une boucle il est demandé un critère qui n’appartient pas à la table de la boucle, SPIP essaie automatiquement de trouver une table liée qui contient le champ demandé.

Dans l’exemple donné, la jointure se fait automatiquement entre les tables spip_documents et spip_documents_liens à laquelle appartient le champ “vu” :

<BOUCLE_doc(DOCUMENTS){0,10}{vu=oui}>
- #FICHIER<br />
</BOUCLE_doc>

Attention : la jointure automatique ne concerne que les critères, pas les balises : dans l’exemple ci-dessus, on ne pourrait pas utiliser #VU dans le corps de la boucle !

Critères : forcer une jointure

Dans l’exemple cité plus haut, on aurait pu forcer la jointure en spécifiant la table à utiliser, de la manière suivante :

<BOUCLE_doc(DOCUMENTS){0,10}{documents_liens.vu=oui}>
- #FICHIER<br />
</BOUCLE_doc>

Une autre manière de faire, moins recommandée (moins générique, et nécessite une déclaration), est d’utiliser une exception de jointure. On la déclare par exemple dans le pipeline declarer_tables_interfaces par :

$interface['exceptions_des_jointures']['vu_documents'] = array('spip_documents_liens', 'vu');

puis on l’utilise dans la boucle

<BOUCLE_doc(DOCUMENTS){0,10}{vu_documents=oui}>
- #FICHIER<br />
</BOUCLE_doc>

Attention : dans ce cas également, la jointure ne fonctionne que pour les critères, pas les balises ! Voir par exemple http://permalink.gmane.org/gmane.comp.web.spip.devel/60476.

Balises : forcer la jointure

Pour utiliser les balises d’une autre table que la table de la boucle, il faut absolument forcer la jointure dans le squelette de manière explicite. Par exemple, pour afficher la valeur du champ vu grâce à la balise #VU :

<BOUCLE_doc(DOCUMENTS spip_documents_liens){0,10}{vu=oui}>
- #FICHIER (#VU)<br />
</BOUCLE_doc>

Cette manière de forcer explicitement la jointure permet aussi de faire fonctionner le critère {vu=oui}.

Attention : la déclaration d’exception de jointure décrite plus haut ne sert pas à fabriquer de nouvelles balises. Dans l’exemple associé “vu_documents” n’est qu’un alias pour les critères !

Balises : champs homonymes

Dans le cas particulier où on veut afficher un champ de la table jointe ayant le même nom qu’un champ de la table de la boucle, il est nécessaire d’utiliser deux boucles. Par exemple, les tables spip_documents et spip_articles ont toutes les deux un champ titre. Dans une boucle de documents, pour afficher le nom du fichier et le titre de l’article associé, il faut faire :

<BOUCLE_image(DOCUMENTS){id_article}>
<BOUCLE_article(ARTICLES){id_article}>
#_image:FICHIER - #_article:TITRE
</BOUCLE_article>
</BOUCLE_image>

ou plus simplement (à l’écriture, parce qu’une deuxième requête sera créée de toute manière) :

<BOUCLE_image(DOCUMENTS){id_article}>
#FICHIER - #INFO_TITRE{article, #ID_ARTICLE}
</BOUCLE_image>

Pour information, la boucle suivante afficherait le titre du document, et pas de l’article

<BOUCLE_image(DOCUMENTS){id_article}>
#FICHIER - #TITRE
</BOUCLE_image>

En effet, SPIP calcule une balise :

  • premièrement en cherchant le champ correspondant dans la table principale de la boucle où elle se trouve,
  • puis, si aucun champ n’est trouvé, dans les tables jointes.

A noter : dans SPIP, pour les balises, il n’existe pas de notation du type #articles.TITRE comme on pourrait le voir en SQL, ou comme on peut le faire pour les critères (voir plus haut).

Déclaration des jointures

Pour déclarer une jointure dans la déclaration d’une table, il faut que les champs de la jointure soient insérés :

  • dans 'key', qui liste les clés (primaire et autres),
  • ou dans 'join', qui liste les champs pour les jointures.

Par exemple, dans le pipeline trucs_declarer_tables_principales d’un objet appelé truc, le code suivant déclare id_truc comme clé primaire, ce qui permettra les jointures sur ce champ :

$tables_principales['spip_trucs']['key'] = array("PRIMARY KEY" => "id_truc");

et le code suivant déclare que les deux champs id_auteur et id_traducteur de la table utiliseront le champ id_auteur de l’autre table en cas de jointure :

$tables_principales['spip_trucs']['join'] = array("id_auteur" => "id_auteur", "id_traducteur" => "id_auteur");

A noter : ces mêmes déclarations peuvent être faites dans le fichier mes_options.php par :

$GLOBALS['tables_principales']['spip_trucs']['key'] = array("PRIMARY KEY" => "id_truc");
$GLOBALS['tables_principales']['spip_trucs']['join'] = array("id_auteur" => "id_auteur", "id_traducteur" => "id_auteur");

Quelques liens

Discussion

3 discussions

  • 3

    Bonjour,

    J’ai « créé » pour mais besoin un plugin avec « la fabrique », ce dernier ajoute 3 objets d’éditions :

    • Profils, avec une table « profils »
    • Expériences, avec une table « experiences » et « experiences_liens »
    • Compétences, avec une table « competences » et « competences_liens »

    Mon soucis n’est pas dans l’utilisation de « La Fabrique » mais dans les jointures et la récupération des informations des différentes expériences et compétences en fonction d’un profil.
    J’ai fait pour l’occasion un squelette simple avec ce code pour test :

    <BOUCLE_table(profils spip_experiences spip_competences){id_profil=1}>
    <h1>#PRENOM #NOM</h1>
    <p>#PROFIL</p> 
    <p>#PERIODE : <strong>#POSTE_OCCUPE</strong></p>
    <p>#TEXTE</p>
    <p>#COMPETENCE - #NIVEAU - #POURCENTAGE</p>
    </BOUCLE_table>

    Comment récupérer l’intégralité des expériences et des compétences lié au profil 1 ?
    Parce que pour l’heure, je n’affiche qu’un seul enregistrement sur les 2 expériences et les 2 compétences liés au profil en question.

    Merci de votre aide.

    • Réponse à moi-même, après une nuit de sommeil et un regard différent sur le problème je l’ai résolu moi même.

      Merci à ceux qui ont cherché ou ce sont posé la question.

    • pierre.laszczak@gmail.com

      Bonjour !

      c’est normal comme comportement.
      Pourquoi ne pas faire plusieurs boucles ?
      Pourquoi utiliser une table pivot de liens ?? :
      id_profil sur experiences et competences ne suffirait-il pas ?

      Mais dans votre cas précis je vois pas pourquoi il faut utiliser une jointure^

    • Bonjour,
      c’est effectivement la solution simple et efficace que Morphée (id_profil sur experiences et competences) m’a suggéré...

      Merci encore.

    Répondre à ce message

  • 1

    Merci Severo pour cette contrib très utile.

    Il semblerait aussi que $interface[’tables_jointures’] le permette aussi, à utiliser dans le pipeline declarer_tables_interfaces. Syntaxe supposée (à confirmer) :

    $interface['tables_jointures']['spip_bibliotheques'][] = 'livres'

    avec spip_livres possédant une clé étrangère (id_bibliotheque) vers spip_bibliotheques

    ++

    • Oui, il y a pas mal de mécanismes pour les jointures, et j’ai pas tout détaillé dans l’article (ni tout compris d’ailleurs). Si tu veux, je te mets comme auteur de l’article et tu rajoutes un paragraphe...

    Répondre à ce message

  • Excellente synthèse effectivement.

    Merci .)

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom