Référence inverse avec CCK

Information importante

En raison d'un grand nombre d'inscriptions de spammers sur notre site, polluant sans relache notre forum, nous suspendons la création de compte via le formulaire de "sign up".

Il est néanmoins toujours possible de devenir adhérent•e en faisant la demande sur cette page, rubrique "Inscription" : https://www.drupal.fr/contact


De plus, le forum est désormais "interdit en écriture". Il n'est plus autorisé d'y écrire un sujet/billet/commentaire.

Pour contacter la communauté, merci de rejoindre le slack "drupalfrance".

Si vous voulez contacter le bureau de l'association, utilisez le formulaire disponible ici, ou envoyez-nous un DM sur twitter.

Ce post consiste juste à présenter une solution au référencement inverse avec CCK.

Pour être plus clair, voici un exemple :
Un site comporte des noeuds de type "établissement" et "édition" (publication).
Le contenu des noeuds de type "établissement" est un contenu statique, bougeant peu.
À l'inverse, les noeuds de type "édition" sont publiés et dépubliés régulièrement par le module schedule.

Le but de la manipulation est de faire apparaître la liste des éditions réalisées par un établissement sur sa page. Dans la pratique, le contributeur crée une édition et indique le ou les établissements auxquels se rapporte l'édition plutôt que de modifier à chaque fois le noeud de l'établissement.

CCK rend possible la création de "Node reference" avec un champ de type autocomplete. Il suffit donc de rajouter un tel champ au type de noeud "édition" (appelons-le "référence").

Il faut ensuite un bout de code (snippet) à insérer dans le template du type "établissement" (module template) ou dans un bloc que l'on fait apparaître avec le type "établissement" :

<?php
$req
="SELECT r.nid,n.title
      FROM   {node_data_field_rfrence} r, {node} n
      WHERE  r.nid=n.nid
      AND    field_rfrence_nid=%d
      AND    n.status=1"
;
$res=db_query($req,$nid);

$liens=array();

while(
$edition=db_fetch_object($res)) {
 
$liens[]=l($edition->title,'node/'.$edition->nid);
}

if(
count($liens)>0) {
  if(
count($liens)==1) {
    echo
theme_item_list($liens,t('Document disponible'));
  } else {
    echo
theme_item_list($liens,t('Documents disponibles'));
  }
}
?>

Notes :

  • le champ "référence" doit être en mode multiple
  • la création du champ "référence" doit avoir entraîné la création de la table node_data_field_rfrence
  • il faut ajouter un index sur le champ field_rfrence_nid de cette table sinon les performances se dégraderont petit à petit.
Forum : 
Version de Drupal : 

Hello,

Quelques petites remarques purement syntaxiques par rapport à ton code :

  • Il ne faut pas entrer en dur dans une requête SQL le nom d'une table créée par CCK (ici, node_data_field_rfrence) car ce nom peut changer sans préavis. Soit tu modélises ta requête avec une View et tu récupères la vue dans ton code PHP avec les fonctions views_get_view() et views_build_view(), soit tu récupères le nom de la table avec la fonction _content_tablename().

  • A priori, la fonction t() attend du texte en anglais.

  • A priori, l'appel d'une fonction de thème se fait en écrivant theme('item_list', $args) et non theme_item_list($args).

Hello Vincent !

Remarques bien senties ;-)

Concernant le nom de la table en dur, c'est vrai que CCK peut en changer le nom sans préavis. Toutefois, le comportement que j'ai analysé de la part de CCK m'amène à penser que cela ne devrait pas être le cas pour cette table (je peux bien sûr me tromper, ce ne sont que des suppositions). Quand on crée un champ avec CCK, 2 cas se présentent : soit le champ est créé dans la table du type de noeud auquel il se rapporte, soit une nouvelle table est créée qui contiendra uniquement les valeurs de ce champ. Le deuxième cas apparaît lorsque l'option "Valeurs multiples" est donnée à ce champ ou lorsque plusieurs types de noeud l'utilisent. Mon champ est en "Valeurs multiples", je suis donc dans le deuxième cas et la probabilité que je le remette en "Valeur unique" est très faible. C'est pour ça que j'y suis allé franco ;-)

Concernant la fonction t(), tu as tout à fait raison, c'est une erreur de ma part.

Idem pour theme_item_list.

Il est trop fort ce Vincent ;-) Comme quoi, ça a du bon de s'exposer à la critique, ça permet d'avoir des avis éclairés et de corriger ses erreurs.

Hello,

Concernant le nom des tables CCK, tu n'as pas tort. Mais ton raisonnement ne couvre pas la possibilité que les développeurs du module CCK changent son fonctionnement ou ses conventions de nommage.

Bon, tu vas croire que je cherche la petite bête, mais c'était juste pour dire qu'en règle générale - et même si c'est très tentant - il faut éviter de faire des requêtes SQL qui tapent directement sur les tables CCK. Le module Views permet justement d'éviter ça alors pourquoi s'en priver ? :)

Mais ton raisonnement ne couvre pas la possibilité que les développeurs du module CCK changent son fonctionnement ou ses conventions de nommage.
il faut éviter de faire des requêtes SQL qui tapent directement sur les tables CCK
Je suis d'accord sur ces points.

Bon, tu vas croire que je cherche la petite bête
Non

Le module Views permet justement d'éviter ça alors pourquoi s'en priver ? :)
Au début, je ne pensais pas que Views permettait de le faire. Comme tu m'as mis le doute, j'ai regardé pour voir si c'était possible ou non.

Et c'est effectivement possible en utilisant les arguments, on sélectionne le champ servant au référencement et on définit le code de gestion des arguments suivant :

<?php
if($type=='block') {
  if(
arg(0)=='node' && is_numeric(arg(1)) && is_null(arg(2))) {
   
$args[0]=(int)arg(1);
  }
}
?>

Par contre, je pense que cela nécessite quand même d'installer un index sur la fameuse table.

Merci beaucoup pour l'astuce. J'ai testé, cela fonctionne, mais les relations ne s'affichent que dans un sens (relations inverse comme prévu). Comment faire pour afficher les relations dans les deux sens ?

Exemple, je fais un lien de A vers B

quand je regarde la page A, je voudrais voir un lien vers la page B dans un block

et

quand je regarde la page B, je voudrais voir un lien vers la page A dans le même block

Merci !

Très intéressant...

Mais dans le cas où l'on affiche plusieurs node sur une page (depuis une view) comment afficher les références inverse pour chaque nodes? Je fais ça avec views_get_view() et views_build_view()?

Le but est d'avoir quelque chose comme ceci:

node1

-refinv1 -refinv3

node2

-refinv1 -refinv2

nodex

-refinvy -refinvz

@d pourquoi ne pas créer deux bloc différent que tu affiches selon de type de node?

Bonjour, je suis particulièrement intéressée par ce développement, cela fait 3 jours que je cherche comment faire sur tous les sites Drupal.
La solution semble être ici mais je ne comprends pas bien toutes les étapes pour en arriver à afficher la liste des éditions sur l'établissement sélectionné.
J'ai bien lu le PDF et vos post seulement :
- je n'ai aps de création de tables même avec un champs en multiples donc le snipept me retourne fatalement une erreur
- si j'utilise l'ajout d'argument, y a-t-il aussi ajout de snippet ?

Bref, pourriez-vous repartir à zero et nous expliciter cela ? Je pense que c'est uen fonctionnalité indispensable.
Merci :) et bravo