WordPress articles similaires en relation sans plugin

Il existe de très bons plugins WordPress pour afficher des articles en relation avec l'article en cours de lecture. Il ne s'agit pas ici de faire mieux qu'eux, mais seulement d'implémenter uniquement ce dont on a besoin et de limiter les accès à la base de données. Car comme la plupart des plugins, de nombreuses requêtes SQL sont faites uniquement pour lire les "réglages" du plugin, les paramètres, etc ...

L'intérêt de ce type de contenu est multiple. D'une part, il améliore le SEO d'un site en ajoutant du contenu similaire. Ensuite, les articles en relation améliore votre taux de rebond, et donc le nombre de pages vues par visiteur sur votre site.

Dans le cas suivant, j'avais besoin d'afficher des articles similaires qui sont liés par les même tags. Il est donc nécessaire d'utiliser le paramètre tag__in de WP_Query. Il faut aussi exclure de la requête SQL l'article déjà en cours de consultation, en utilisant post__not_in. Ensuite, dans le cas où il n'y aurait pas assez d'article avec les mêmes tags, j'élargis la requête aux catégories communes avec category__in.

Afin de mettre en avant du contenu plébiscité par les internautes, j'ai décidé de trier les résultats par nombre de vues. Une requête order by meta_key est donc nécessaire. Enfin, le site pour lequel ce script a été réalisé est orienté "tags content".

Après analyse, 75 % des requêtes concerneront des tags qui auront suffisamment d'articles. Du coup, la requête pour les catégories sera plutôt rare. Afin de ne pas surcharger inutilement le process SQL, j'ai décidé de faire 2 requêtes distinctes qui seront fusionnées si nécessaire. Le requête des catégories est lancée uniquement s'il n'y a pas assez d'articles via la requête des Tags. Dans ce cas, il faudra ajouter des exceptions afin de s'assurer que les deux même articles ne soient pas retournés, pour éviter tout doublon.

function patrice_related_post( $per_page = 3 ) {
   $post_tag = get_the_tags(); // tags of current post
   $loopTag  = ''; // init empty
   $loop_cat = ''; // init empty
   if ( $post_tag ) { // we have at least one tag
      $tags = '';
      foreach ( $post_tag as $tag ) {
         $tags .= $tag->term_id . ',';
      }
      if ( $tags ) { // just in case ...
         $args    = array(
            'tag__in'        => array( $tags ), // Must be an array
            'post__not_in'   => array( get_the_ID() ), //the current psot ID
            'posts_per_page' => $per_page, // How many result to display
            'meta_key'       => 'views', // Order by view -> get the msot viewed related articles
            'orderby'        => 'meta_value_num',
            'order'          => 'DESC',
         );
         $loopTag = new WP_Query( $args );
      }
   }
   if ( $loopTag ) {
      $found = $loopTag->post_count; // get the number of results
   } else {
      $found = 0; // zero if nothing
   }
   if ( $found < $per_page + 1 ) { // We have less tag results than $per_page. We msut complete with categories results
      $postids = array( get_the_ID() ); // Current psot ID must not be in loop
      $uniqueposts = $postids; // init unique array post.
      if ( $found > 0 ) { // if we have at least one tag result
         foreach ( $loopTag->posts as $item ) {
            $postids[] = $item->ID; //create a new query only of the post ids
         }
         $uniqueposts = array_unique( $postids ); // Avoid duplicate IDS
      }
      $cats = wp_get_post_categories( get_the_ID() ); // Get current post categories
      if ( $cats ) { // Do only if we have category
         $relCat = array(
            'category__in'   => $cats, // array of cat id
            'post__not_in'   => $uniqueposts, // array of current post id and tags psot ID
            'posts_per_page' => ( $per_page - $found ), // Need number - count result tags loops
            'meta_key'       => 'views',
            'orderby'        => 'meta_value_num',
            'order'          => 'DESC',
         );
         $loop_cat = new WP_Query( $relCat );
      }
   }
   if ( ! empty( $loop_cat ) && ! empty( $loopTag ) ) { // The 2 loops are ready
      $loop             = new WP_Query(); // create empty WP_Query
      $loop->posts      = array_merge( $loopTag->posts, $loop_cat->posts ); // merge the both loops and set it as posts object
      $loop->post_count = $loopTag->post_count + $loop_cat->post_count; // update post count for the merged loop
   } else {
      if ( ! empty( $loopTag ) ) { // We have a tag result, we prefer have it instead of nothing
         $loop = $loopTag;
      } elseif ( ! empty( $loop_cat ) ) { // We do not have tag result, but have a category loop result
         $loop = $loop_cat;
      }else{
         //We have no results, What's Wrong with our writter ? It should have at least one category.
         // Doh, perhaps it's in preview mode ... so we need an exception for it to display the most readed articles, better than nothing ?
         $relDefault = array(
            'post__not_in'   => array(get_the_ID()), // array of current post id
            'posts_per_page' => $per_page, // Need number - count result tags loops
            'meta_key'       => 'views',
            'orderby'        => 'meta_value_num',
            'order'          => 'DESC',
         );
         $loop = new WP_Query( $relDefault );
      }
   }
   // the magic happen here ...
   if ( $loop->have_posts() ) {

      while ( $loop->have_posts() ) : $loop->the_post(); ?>
         <?php get_template_part( 'templates/partials/single/related.blade' ); ?>
         <?php

      endwhile;

   }
   wp_reset_query(); // Reset the query
   // The END .... My franglish is Good, isn't it ? ;)

}

Il suffit ensuite de simplement appeler cette fonction dans votre fichier single.php pour afficher les articles en relation.

Pour afficher 5 articles en relation :

patrice_related_post( 5 )

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.