Related posts voor Drupal

Mijn artikels hebben categorieën en trefwoorden. Ik wil per artikel een lijst van verwante artikels, op basis van de trefwoorden (tags) die eraan gekoppeld zijn.

Ik weet niets van modules maken voor Drupal — dat zal voor dán eens zijn — dus doe ik het allemaal zuiver persoonlijk voor mezelf. In een functie die ik bij gebrek aan betere plaats in template.php steek.

1. Lijst van tags voor een gegeven node krijgen

$tags=taxonomy_node_get_terms_by_vocabulary($node, 2);
$taglist=implode(",",array_keys($tags));

Simpel: taxonomy_node_get_terms_by_vocabulary geeft mij een array van alle tags (vocabulary ID=2) voor een gegeven node. Ik heb er enkel de keys van nodig, en dan nog enkel de keys als een lijst voor in een SQL query.

2. Lijst van nodes gesorteerd op aantal gemeenschappelijke tags

Alle nodes gekoppeld aan de tags uit de lijst is dit:

SELECT * FROM node LEFT JOIN term_node ON node.vid=term_node.vid WHERE tid in ($taglist)

Dat gegroepeerd per node-ID en aflopend gesorteerd op aantal tags per node, is dit:

SELECT node.nid FROM node LEFT JOIN term_node ON node.vid=term_node.vid WHERE tid in ($taglist) GROUP BY node.nid ORDER BY count(tid) DESC

…en dat geeft wat ik wil: een lijst van node-IDs, aflopend gerangschikt op “verwantschap”, ‘t is te zeggen, op aantal gemeenschappelijke tags met de oorspronkelijk doorgegeven node-ID.

Kleine verfijningen: bijkomend ook aflopend sorteren op datum (ORDER BY created DESC), de huidige node er niet bijzetten (node.nid<>$nid), enkel gepubliceerde nodes tonen (node.status<>0) een optie toevoegen om het aantal te beperken (LIMIT $limit) en omdat ik toch aan het hacken ben: meteen ook de titel en het aantal reacties erbij ophalen, dan kan ik in één moeite een geformatteerd lijstje outputten.

Alles tesamen geeft dat dan:

function get_related($nid,$limit) {
  $node=node_load($nid);

  $tags=taxonomy_node_get_terms_by_vocabulary($node, 2);
  $taglist=implode(",",array_keys($tags));

  $related=db_query("SELECT node.nid nid, title, 
     comment_count FROM node LEFT JOIN term_node ON 
     node.vid=term_node.vid LEFT JOIN node_comment_statistics 
     ON node.nid=node_comment_statistics.nid WHERE tid 
     IN (%s) AND node.nid<>%d AND node.status<>0 
     GROUP BY node.nid ORDER BY count(tid) DESC, 
     created DESC LIMIT %d", 
  $taglist,$nid,$limit);

  while ($rel=db_fetch_object($related)) {
    $result.="<p>".l($rel->title,"node/".$rel->nid);
    $result.=" ($rel->comment_count)</p>\n";
  }
  return $result;
}

Dat moet dan nog wat opgeleukt worden, natuurlijk: sanity checks allerhande, een lijst van random dingen geven uit de laatste maand als er geen verwante items gevonden werden bijvoorbeeld. Maar het werkt toch al in eerste instantie.

6 reacties op “Related posts voor Drupal”

  1. *kuch* met views *kuch*

    Ik kan trouwens ten stelligste de Views en CCK videos van Lullabot aanraden die een paar weken geleden zijn uitgebracht. Documentatie en nuttige voorbeelden is (was) namelijk iets dat ontbreekt voor deze modules.

  2. Tja.

    Het ziet er veel werk uit om tot een query te komen die dan een node output die dan toch nog eens gestyled moet worden, denk ik. En tenzij ik me vergis, zoekt dat enkel nodes die precies dezelfde taxonomy terms delen en sorteert het ze niet op verwantschap?

  3. Er is een module “simular by terms”: drupal.org/project/similarterms die dit doet (denk ik).

    Wie weet kan je die gebruiken… Of kan ze dienen als inspiratie.

  4. Serieus? Waarom eigenlijk?

    Voor de duidelijkheid: al wat ik gedaan heb, zat in views en getemplated, maar ik ben ervan teruggekomen.

    Ik had vanalles in views gestoken, maar als het meer is dan wat rechttoe rechtaan css-customizeerbare layoutwijzigingen, moet ik tóch outputten als node in plaats van als fields, en dan moet ik tóch in de template zitten klooien en met php links en rechts in de beheersinterface zitten…

    En dan zaten er soms stukken inhoud lichtjes gewijzigd die ik niet via node-templates kon themen en waar ik via block- of view-templates moest aan prutsen, en uiteindelijk met een paar functies in template.php en een wat uitgebreidere page.tpl.php kan ik alle mogelijk pagina-indelingen doen, zonder vast te zitten aan die vervelende blocks.

    Akkoord dat het veel eenvoudiger is voor heel eenvoudige dingen, maar ik liep er op den duur in verloren. Op deze manier zijn er voor de “speciallekes” maar twee plaatsen om te kijken: page.tpl.php en template.php.

    Tenzij ik het he-le-maal verkeerd doe natuurlijk, en dan word ik het graag uitgelegd. 😀

Reacties zijn gesloten.