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 reliée à 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.
Ce code se place dans le fichier archive-CPT.php de votre thème, ou mieux de votre thème enfant, en remplaçant CPT par l’identifiant de votre type de contenu : archive-livre.php pour un type livre, par exemple. WordPress n’utilise ce modèle que si le type de contenu a été déclaré avec l’argument has_archive. Remplacez aussi NOM_CPT et NOM_TAXONOMIE, aux lignes surlignées, par les identifiants de votre type de contenu et de votre taxonomie.
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 titre de l’archive est placé hors de la boucle principale, qui l’aurait répété pour chaque contenu, et chaque terme devient un titre de niveau 2. Sans posts_per_page à -1, chaque requête s’arrêterait au nombre fixé dans Réglages > Lecture par le réglage « Nombre de publications récentes affichées sur les pages d’archive » (10 par défaut). wp_reset_postdata() rétablit le contenu courant après chaque boucle, et le test is_wp_error() évite des avertissements PHP si le nom de la taxonomie est erroné.
Si votre taxonomie est hiérarchique, comme les catégories, un contenu classé dans un terme enfant apparaît sous ce terme et sous son parent : passez include_children à false pour ne l’afficher que sous son propre terme. Les termes sans contenu et les contenus sans terme n’apparaissent pas.
Le reste vous l’aurez compris n’est que mise en forme HTML / CSS. Ici, je me base sur les classes de Bootstrap 3 : depuis Bootstrap 4, img-responsive s’appelle img-fluid. Adaptez ces classes à votre thème.
Et avec un thème à blocs ?
Avec un thème à blocs, comme Twenty Twenty-Five, ce fichier PHP n’est pas la bonne solution. WordPress l’utilise bien, mais get_header() et get_footer() n’y trouvent ni header.php ni footer.php : ils chargent alors un en-tête et un pied de page de secours, obsolètes depuis WordPress 3.0, au lieu de ceux de votre thème. Placez plutôt la même logique dans un code court (shortcode), à ajouter au fichier functions.php de votre thème enfant :
Ouvrez ensuite Apparence > Éditeur > Modèles, cliquez sur Ajouter un modèle et choisissez Archives : Livre, Livre étant le nom de votre type de contenu. Ce choix n’apparaît que si le type de contenu a été déclaré avec has_archive et show_in_rest à true.
Dans la fenêtre Choisir une composition qui s’ouvre, sélectionnez le Contenu de secours, tiré des modèles de votre thème. Remplacez-y le bloc Boucle de requête par un bloc Code court contenant [wpc_cpt_terms], puis cliquez sur Enregistrer.
Pour maîtriser l’adresse de cette archive, voyez comment définir l’URL d’archive d’un Custom Post Type.
15 réponses
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
Bonjour,
J’ai créé une page template comme celle-ci, mais rien ne s’affiche est-ce normal ?
(a qui puis-je envoyer le lien en MP pour vérification ?)
Phil
Ce tutoriel est plutôt technique et je vous invite à vérifier chaque ligne de code en fonction de votre site au préalable.
@Julio : je pense qu’il y a une coquille sur le foreach non ? Et sinon oui ça fonctionne nickel. 🙂
Merci à Aurélien et à Julio. J’ai eu un casse tête similaire avec des query sur mesure sur les archives des custom taxonomy et c’est le pre_get_posts qui m’a sauvé.
Oui très pratique ! Et différentes techniques existent.
P.S : oui oui 😉
Merci les gars!
@Julien, pourquoi serait suicidaire de mettre tous les articles sur une seule page? (pour exemple, une page dédiée à une liste d’articles d’une catégorie spécifique)…
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 :O
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
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 !
auto réponse, il faut lire « is_post_type_archive( $post_type ) » au lieu de « is_home() » et le pastebin du hook ici : http://pastebin.com/Y9ywcCHp
Tout fonctionne au poil ! Merci bien !
Reste un point : vider le transient sinon le cache ne se régen pas. Il faut le faire au save_post, delete_post, save_term, delete_term, etc etc
Justement je me suis aperçu que effectivement ça ne vidait pas le cache… tu mets à jour ton code ?
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 ? ^^