Créer une page d’archive d’un custom post type en classant selon les termes d’une taxonomie

Créer une page d’archive d’un type de contenu est relativement simple, il convient de nommer le fichier archive-CPT.php dans le dossier de votre thème. La problématique ici consistait non seulement à lister tous les contenus mais en tenant compte des termes qui leur étaient reliés.

Si je devais résumer, voici le résultat souhaité :

  • Terme 1
    • Contenu A
    • Contenu B
    • Contenu C
  • Terme 2
    • Contenu A
    • Contenu B
    • Contenu C
  • Terme 3
    • Contenu A
    • Contenu B
    • Contenu C

Et ainsi de suite jusqu’à ce que tous les contenus aient été listés dans ma page d’archive.

Pour ce faire, j’ai donc commencé par lister les termes à l’aide de la fonction get_terms en spécifiant le nom de la taxonomie reliait à mon type de contenu.

Ensuite, pour chaque terme, une requête WP_Query pour récupérer les contenus qui sont bien associés à ce terme.

Une fois dans la boucle, à vous de choisir les éléments que vous souhaitez récupérer : le titre, le permalien, l’image à la une, etc.

Voici l’intégralité du code du tutoriel avec des éléments facultatifs pour bien présenter les choses dont le titre de la page d’archive. Le reste vous l’aurez compris n’est que mise en forme HTML / CSS. Ici, je me base sur le framework CSS de Twitter Bootstrap.

<?php if (!defined('ABSPATH')) die('Restricted Area'); ?>
<?php get_header(); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<header class="page-header">
<h1 class="container"><?php post_type_archive_title(); ?></h1>
</header>
<?php endwhile; endif; ?>
<div class="content">
<div class="container">
<?php
$taxonomy = 'NOM_TAXONOMIE';

$term_args = array(
 'orderby' => 'name',
 'order' => 'ASC'
 );

$terms = get_terms($taxonomy,$term_args);
 
if ($terms) { foreach( $terms as $term ) {
?>
 
<?php 
$args = array(
'post_type' => 'NOM_CPT',
'tax_query' => array(
array(
'taxonomy' => 'NOM_TAXONOMIE',
'terms' => array($term->term_id),
'include_children' => true,
'operator' => 'IN'
)
)
);
$my_query = new WP_Query($args); if( $my_query->have_posts() ) { ?>
<div class="row">
<h1 class="term-title"><?php echo $term->name; ?></h1>

<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<div class="col-sm-2">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('thumbnail', array('class' => 'img-responsive aligncenter')); ?>
<?php endif; ?>
<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php _e('Permanent link to ', 'textdomain'); ?><?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
</div>
<?php endwhile; ?>
</div>
 
<?php } 
 } } ?>
<?php wp_reset_query(); ?>
</div>
</div>
<?php get_footer(); ?>

Crédits photo : Andrea Pesce

15 commentaires

  1. Julio Potier

    Hello !
    As-tu remarqué que celà ne charge que les X articles pour chaque terme (X=selon les options de lecture de ton WP) ? Tu as oublié de mettre « -1 » en « posts_per_page » !

    Aussi, comme tu es sur une page d’archives, WordPress a déjà une requête qu’il a été faite pour toi, la « main query » et tu ne l’utilises pas !?

    Puis, tu vas faire une WP_Query pour chaque terme ? Omg

    Aussi, n’oublie pas que si tu souhaites afficher TOUS les articles sur une page, c’est assez suicidaire, ça va si tu en a peu sinon … PAF la pastèque.

    Pour en revenir à la main query, je pense qu’il serait mieux de toucher à pre_get_posts, check si on est en is_home pour cette main query, dans ce cas mettre -1 en posts_per_page, ce qui va te permettre d’avoir tous les articles dans la page d’archive.

    Maintenant, plus aucune query à faire, TOUS tes articles sont là, à toit de filtrer l’affichage à base de has_term.
    Et enfin, tout ceci manque de cache, où est le transient ? A chaque reload de chaque visiteur je dois tout re-récup ? wowowow.

    Bon, je viens de tester le code et le faire à ma sauce : http://pastebin.com/fwnMEgYw
    Qu’en dis-tu ? Il prends en charge les transients (je suis passé de 335 reqs à 61), 0 WP_Query, pas de reset query car pas de the_post qui écrase la globale, chacune des fonctions utilisée peut prendre un post ou un ID en param, et ça liste vraiment tout grâce à ce hook à mettre en plugin/mu-plugin/functions.php (au choix).

    (et code commenté ^^)

    Bisous

    1. Aurélien Denis auteur de l’article

      Hey, pour tout te dire je me demandais quand tu allais enfin commenter mon code !

      Je vais tester cela dès demain vu qu’il s’agit d’un projet en cours héhé. Oui le posts_per_page je pensais l’avoir mis mais non…

      Merci l’ami !

          1. Julio Potier

            Voilà quelques hooks qui devraient faire l’affaire.
            http://pastebin.com/9ABV2ByF
            Aussi, après réflexion, il faut mettre ce transient en cache timé pendant 1 an, le but est qu’il ne soit chargé qu’à la demande et pas non stop (autoload) car il pourrait alors être assez gros et faire grimper la mémoire PHP utilisée pour rien.
            « 365*DAY_IN_SECONDS » pour le timeout

            Pas trop décousue comme réponse ?

  2. Jonathan

    Bonjour Aurélien

    Je cherche à faire la même chose mais sur les pages des mots clés ( pages des tags). Pour le moment, wordpress affiche tous les articles qui contiennent chaque mots clés. Moi, je voudrai qu’il m’affiche les articles mais classés par catégorie.

    Exemple :

    Page d’un mot clé :

    Catégorie 1
    Contenu A
    Contenu B
    Contenu C
    Catégorie 2
    Contenu A
    Contenu B
    Contenu C
    Catégorie 3
    Contenu A
    Contenu B
    Contenu C

    De plus, j’aimerais également qu’il ne m’affiche pas les articles provenant des sous-catégories d’une catégorie en particulier. est ce possible de faire ca ?

    Merci pour votre aide

Laisser un commentaire