SPIP 3, Documents, Mots Les liaisons dangeureuses !

, par Matthieu Marcillaud

SPIP 3 permet d’attacher des mots à des documents, et il permet également de taguer des documents avec des mots clés. Fort pratique certainement, ce qui devient plus délicat, c’est ensuite les boucles à réaliser pour retrouver tout cela. Au vu des nombreuses questions sur les listes d’utilisateurs, voici un petit peu d’explication du fonctionnement.

Un énième message d’un utilisateur de SPIP et concepteur de squelette ne comprenait pas pourquoi sa boucle documents ne retournait rien.

En fait il s’attendait à ce que la boucle retourne la liste des documents qui ont un mot clé donné (les mots clés taguent des documents donc). C’est une compréhension fort logique, vu que c’est ce que fait la boucle :

Les tables de liaisons

Mais ce n’est pourtant pas ce qui se passe avec la boucle documents. La différence est simple, il existe une table SQL « spip_documents_liens » qui sert de pivot (on parle souvent de table de liaison) où est stockée donc l’information disant tel document est lié à ceci, cela, c’est à dire à des objets éditoriaux (articles, rubriques, mots, tout ce que l’on veut).

Il existe la même table « spip_mots_liens » qui sert de pivot pour indiquer que tel mot est attaché à tel objet éditorial, lorsqu’on tague des articles, des documents d’un mot clé.

Mais il n’existe pas de table « spip_articles_liens ».

Cas non ambigus

Lorsqu’on écrit dans une boucle ARTICLES le critère {id_mot}, SPIP recherche comment il peut faire pour honorer la demande. Il cherche donc si la table SQL spip_articles possède un champ « id_mot » (ce qui n’est pas le cas), et du coup tente de trouver une construction de liaison entre tables SQL (on parle de jointure) qui permet d’obtenir ce id_mot qui est demandé. SPIP remarque que spip_mots_liens possède un champ « id_mot » et va donc demander une jointure avec cette table.
Il pourrait aussi rechercher une table ayant le couple de champs « objet » et « id_objet » et faire une jointure dessus en indiquant, du coup, que objet=mot et id_objet=l'identifiant.

Pour aller plus loin, disons simplement que s’il y a plusieurs possibilités de jointure pour obtenir id_mot, SPIP choisira la jointure la plus courte, c’est à dire qui nécessite d’interroger le moins de tables SQL possibles.

Cas ambigus

Indiquer un critère {id_mot} sur une boucle DOCUMENTS est plus ambigu. Effectivement, SPIP peut choisir de prendre le mot soit sur la liaison spip_documents_liens, soit sur la liaison spip_mots_liens. Les deux étant corrects, mais ils n’ont pas la même signification.

Il faut donc savoir que dans ce cas, SPIP choisit de préférence une liaison avec la même table que celle de la boucle, c’est à dire que comme nous sommes dans une boucle DOCUMENTS, SPIP choisira de préférence la liaison avec spip_documents_liens.

Alors, pourquoi y a t’il deux tables de liaisons possibles avec les documents ou avec les mots ? et à quoi servent-elles ? qu’est-ce qui les différencient ?

Des mots sur des documents, des documents sur des mots

Pour expliquer ce qui se passe :

  • Les documents en SPIP 3 peuvent être sur n’importe quel objet (y compris les mots) (des mots peuvent avoir des documents attachés)
  • Les mots en SPIP 3 peuvent être mis sur n’importe quel objet (y compris les documents) (des documents peuvent être tagués par dés mots)

On voit bien ici que c’est délicat pour SPIP de comprendre ce que signifie (DOCUMENTS){id_mot} : est-ce qu’on veut ?

  • les documents d’un mot clé ?
  • les documents tagués d’un mot clé ?

Il faut donc faire un peu d’analyse de fonctionnement de SPIP pour comprendre ce qui va se passer :

  • Lorsqu’on lie un document à un objet, la liaison est stockée dans la table spip_documents_liens
  • Lorsqu’on lie un mot à un objet, la liaison est stockée dans la table spip_mots_liens

Ce que SPIP va décider lorsqu’il y a ambiguïté, c’est à dire comme ici (DOCUMENTS){id_mot} alors qu’il existe les 2 tables spip_documents_liens et spip_mots_liens, c’est qu’il va préférer interpréter cela comme une liaison sur la table de lien de la boucle en cours, c’est à dire sur spip_documents_liens, ce qui signifie donc que ça va retourner « les documents attachés à un mot clé »

Pour lever les ambiguïtés, on peut indiquer, donc, la relation du lien de plusieurs manières, lorsqu’on veut l’autre relation :

  • Soit en l’indiquant comme table : (DOCUMENTS mots_liens){id_mot}
  • Soit en l’indiquant dans le critère (DOCUMENTS){mots_liens.id_mot}

Il faut noter que mettre simplement (DOCUMENTS){mots.id_mot} n’est pas suffisant pour lever l’ambiguïté.

D’autres exemples :
Liaison spip_documents_liens (Les documents attachés à un mot)

Liaison spip_mots_liens (Les documents tagués d’un mot)

Attraper les documents tagués avec un mot clé appartenant à un certain groupe :