Comment afficher les publications sur une page de catégorie, divisées en sous-catégories respectives • WPShout

By | août 19, 2020

tuto wordpress

Supposons que vous ayez une page de catégorie sur laquelle vous êtes invité à afficher tous les articles appartenant aux sous-catégories de cette catégorie. Jusqu'à présent, pas de soucis – une page de catégorie affiche par défaut tous ses messages descendants, qu'ils appartiennent directement à cette catégorie ou à l'une de ses sous-catégories. Mais voici la torsion: disons que vous devez les afficher de manière à ce que les noms des sous-catégories soient affichés (défi n ° 1), et sous le nom de chaque sous-catégorie, vous devez afficher tous ses messages (défi n ° 2).

Permettez-moi de vous donner un exemple de cas où vous souhaiteriez réaliser une telle chose: par exemple, si vous aviez une catégorie principale nommée "Écoles à l'échelle de l'État" qui comportait des sous-catégories, chacune étant une ville, et les postes étaient les écoles dans cette ville (chaque message détaillant les propriétés de ladite école). Un autre cas pourrait être que la catégorie principale est une année, les sous-catégories sont les mois de cette année et les messages sont des événements qui se sont déroulés ce mois-là.

Voici une illustration de la structure de page de catégorie requise:

messages dans les catégories et sous-catégories

Structure de la page de catégorie basée sur le vecteur infographique créé par freepik

Cet article nous guidera étape par étape pour atteindre cet objectif.

Résumé du fonctionnement des catégories dans WordPress

Avant de commencer, examinons rapidement le fonctionnement des catégories dans WordPress. Comme indiqué précédemment, le comportement par défaut d'une page de catégorie est d'afficher une liste de tous les articles de cette catégorie particulière. Le fichier de modèle dans le thème qui est chargé de rendre l'affichage de la catégorie est category.php.

Si nous voulons qu'une certaine catégorie soit affichée différemment, nous la ciblons avec son propre fichier modèle: le nom du fichier commencera par le mot Catégorie, suivi d'un tiret, puis du slug de la catégorie ou de son identifiant. Ce format de nom de fichier permet au moteur WordPress de le reconnaître en tant que modèle de catégorie spécifique. Par exemple, catégorie-13.php affichera les articles de la catégorie dont l'ID est 13, et le category-mycat.php afficherait les messages dans la catégorie dont le slug est mon chat.

Dans le cas que je décrirai dans cet article, j'ai décidé d'utiliser le slug car l'administrateur du site en a le contrôle et il peut donc être conservé sur différents sites. Ceci est par opposition à un identifiant qui est généré automatiquement. Par conséquent, nous devrons changer le nom du fichier modèle sur chaque site pour tenir compte des différents identifiants de catégorie. Cela, bien sûr, n'est pas pratique.

Bien que ce fichier de modèle se charge d'afficher les articles sur la page, l'autre problème important est d'obtenir les données – comme nous l'avons déjà noté, par défaut, WordPress ne fournit pas les données sur les sous-catégories dans une page de catégorie.

Il existe plusieurs façons de récupérer les sous-catégories et les articles qui leur appartiennent – nous pouvons utiliser les fonctions WordPress courantes, ou nous pouvons construire une requête $ wpdb personnalisée. Ce cas m'a obligé à utiliser une requête personnalisée, pour des raisons que je vais expliquer maintenant.

Pourquoi une requête $ Wpdb personnalisée?

Je dois admettre que je ne me souviens pas avoir jamais eu à écrire une requête SQL personnalisée dans WP – j'ai toujours réussi à faire ce qui était nécessaire et à obtenir les données requises en utilisant des requêtes WordPress intégrées. Dans ce cas, cependant, je crois qu'il y aurait des problèmes de performances majeurs si nous avions choisi d'autres moyens de récupérer les données. Laissez-moi vous guider à travers le processus de réflexion qui m'a conduit à succomber à l'écriture SQL avec mes doigts nus.

Nous commencerons par identifier les données que nous Avoir et ce que nous avoir à obtenir.

Nous avons:

  1. L'identifiant de la catégorie principale
  2. Un tableau de publications appartenant aux sous-catégories de la catégorie principale (le $ posts tableau global).

Nous avons besoin:

  1. Les identifiants des sous-catégories
  2. Une liste qui connecte chacun de ces ID de sous-catégorie aux articles qui lui appartiennent

Obtenir les identifiants des sous-catégories

C'est en fait relativement simple puisque nous pouvons utiliser le get_terms () fonction, en lui transmettant l'ID de la catégorie parente dans le parent champ. Vous pouvez voir un exemple d'utilisation dans cette réponse WPSE.

Obtenir la sous-catégorie à laquelle appartient chaque article

Ceci, cependant, est la partie difficile depuis le $ post l'objet ne comporte aucun champ reliant la publication à un identifiant de catégorie. Par conséquent, afin de récupérer la relation, nous pouvons emprunter l'un de ces deux chemins:

  1. Parcourez toutes les sous-catégories récupérées dans la section précédente, et pour chacune d'elles exécutez le get_posts () fonction, en lui passant l'ID de sous-catégorie.
    Ensuite, en utilisant les données de chaque get_posts (), nous pouvons afficher ce qui est nécessaire.
    Le principal inconvénient de cette méthode est la nécessité d'accéder à la base de données (bien qu'en utilisant get_posts ()), autant de fois qu'il y a de sous-catégories – pas très performantes. Le deuxième inconvénient est que cette méthode rend le $ posts baie redondante, et c’est un gaspillage de ressources.
  2. L’alternative consiste à faire l’inverse et à obtenir les ID des sous-catégories à l’aide des ID de publication. Cela signifie parcourir le $ posts tableau, et pour chaque article, obtenir sa catégorie en utilisant le get_categories () fonction. Ceci, en soi, est très peu performant, car en supposant que nous ayons au moins quelques dizaines de messages, cela signifie accéder à la base de données plusieurs fois. En plus de cela, nous devrons enregistrer les données dans un tableau, puis les parcourir en boucle pour afficher les sous-catégories et leurs publications.

Comme ce sont les principaux moyens d'obtenir les informations et que chacun d'entre eux a des problèmes de performances, sans parler de la production de code détaillé pour fonctionner, j'ai décidé d'utiliser la requête SQL personnalisée plus concise et plus performante.

Maintenant que nous comprenons le grand schéma des choses, nous pouvons entrer dans les détails de l'implémentation du code.

Plonger dans le code

Nous commencerons par (1) récupérer tous les articles de la catégorie, puis (2) nous créerons une fonction qui obtient une liste des sous-catégories et des ID de publication appartenant à chacune de ces sous-catégories. Après avoir obtenu ces données, (3) nous appellerons cette fonction à partir du fichier modèle que nous créerons pour cette catégorie spécifique, puis nous (4) analysons les informations de l'article par sous-catégorie, et (5) l'utilisons pour créer le HTML de la page.

1. Obtenons tous les messages de la catégorie

Nous allons commencer par l'étape la plus simple: obtenir tous les messages de la catégorie sans pagination. Pour ce faire, nous allons attacher une fonction à la pre_get_posts crochet et passe -1 comme le nombre d'articles à récupérer lorsqu'il obtient les articles de notre catégorie donnée:

$ main_cat_id = 0;

function init_variables () 
if (term_exists ('main-cat', 'category')) 
main_cat_id = get_category_by_slug ('main-cat') -> term_id;



function hook_into_wordpress () 
add_action ('pre_get_posts', 'pre_get_posts');

public function pre_get_posts ($ query) 
if (! is_admin () && $ query-> is_main_query ()) 
/ *** Vérifiez que l'identifiant de la catégorie principale existe sur le site, puis vérifiez que nous sommes sur la page de cette catégorie *** /
if (term_exists (main_cat_id, 'category') && $ query-> is_category ($ main_cat_id)) 
$ query-> set ('posts_per_page', - 1);



Comme vous l'avez peut-être remarqué, nous appliquons ce code à une catégorie spécifique avec un slug spécifique, chat principal. Bien que cette méthode ne soit pas idéale en ce sens que si nous voulons étendre ce comportement à d'autres catégories, nous devrons changer le code, nous allons avec cet exemple simplifié; permettre plus de flexibilité nous amènerait au-delà de la portée de cet article.

2. Obtenons les sous-catégories et les identifiants de publication qui leur sont attribués

Dans cette section, nous allons créer une fonction qui obtient une liste des sous-catégories et des ID de publication appartenant à chaque sous-catégorie.
Ce défi est double: tout d'abord, lorsque nous sommes dans la page des catégories, nous n'avons aucune donnée sur les sous-catégories, ni du côté des catégories (y a-t-il des sous-catégories, et si oui, qui elles sont) ni du côté de la publication (les objets de publication, stockés dans le $ posts variable globale, n'ont aucune propriété qui les attribue à une catégorie). Si nous voulons des informations sur les sous-catégories, même les plus triviales telles que leurs noms, nous devons les récupérer dans la base de données.

Par conséquent, notre seul moyen d’obtenir des informations sur les sous-répertoires est de récupérer à partir de la base de données une liste des sous-catégories de la catégorie principale, et pour chaque sous-catégorie – une liste des ID de publication séparés par des virgules qui lui appartiennent.

Nous allons relever le premier défi en utilisant deux tableaux: wp_term_taxonomy et wp_terms .
le wp_term_taxonomy table stocke des informations sur les relations entre les différentes catégories, en utilisant 2 colonnes principales: parent et term_id. C'est donc le tableau que nous allons interroger pour savoir quelles sont les sous-catégories de la catégorie principale, et nous le ferons en lui envoyant l'ID de la catégorie principale en tant que parent, et sélectionnez tous les term_ids – qui sont les ID de sous-catégorie – dont parent colonne est l'ID de la catégorie principale.
le wp_terms table contient les informations sur chaque catégorie – son nom, son slug, etc. term_ids que nous avons récupéré du wp_term_taxonomy table, nous sélectionnerons les noms des sous-catégories du
wp_terms table.

Le deuxième défi consiste à utiliser le wp_term_relationships table. Cette table a un object_id colonne et une term_taxonomy_id colonne, et chaque ligne représente une connexion entre un objet (une publication, un fichier multimédia, ou une telle entité unique dans WordPress) et un terme (qui peut être une catégorie, une balise ou tout type d'entité de groupe) qui lui est attribué. Par conséquent, nous pourrions théoriquement interroger cette table en envoyant les ID de sous-catégorie comme term_ids, et récupérez tous les articles appartenant à cette sous-catégorie. Cependant, cela nous donnerait un ensemble de données de lignes pour chaque sous-catégorie, qui est plus difficile à manipuler. Par conséquent, nous l'interrogerons de manière à obtenir une ligne par sous-catégorie, et cette ligne aura une colonne avec une liste d'ID de publication séparés par des virgules.

Un exemple d'ensemble de résultats de données:

Nom term_id post_ids
janvier 238 451755, 450433, 452135, 451991, 451944, 452169
février 241 452295, 452421, 450619, 452410, 452402
Mars 233 451702, 448953, 451685, 445431

À cette fin, nous utiliserons le PAR GROUPE Fonction MySql pour regrouper les term_ids, et nous utiliserons également le GROUP_CONCAT qui créera une liste séparée par des virgules (ou tout autre séparateur de votre choix) object_ids.

C'est donc la requête qui obtient toutes les informations dont nous avons besoin – (1) les ID de sous-catégorie de la catégorie principale, (2) leurs noms et (3) une liste des ID de publication appartenant à chaque catégorie. Nous allons mettre dans une fonction appelée getChildCategoriesAndPosts :

    $ childCategories = $ wpdb-> get_results ("SELECT $ wpdb-> prefix terms.name, $ wpdb-> prefix terms.term_id, GROUP_CONCAT ($ wpdb-> prefix term_relationships.object_id SEPARATOR ',') AS post_ids
FROM $ wpdb-> préfixe term_taxonomy
INNER JOIN $ wpdb-> prefix term_relationships sur $ wpdb-> prefix term_relationships.term_taxonomy_id = $ wpdb-> prefix term_taxonomy.term_id
INNER JOIN $ wpdb-> prefix termes sur $ wpdb-> prefix terms.term_id = $ wpdb-> prefix term_taxonomy.term_id
O wp_term_taxonomy.parent = $ cat
GROUP BY $ wpdb-> prefix terms.term_id
ORDER BY $ wpdb-> préfixe terms.name; ");

Pour parcourir facilement la liste des ID de publication, nous allons convertir la liste en tableau:

foreach ($ childCategories as $ child_category) 
      $ child_category-> post_ids = exploser (',', $ child_category-> post_ids);

Si vous vous demandez s'il est absolument nécessaire d'écrire une requête SQL personnalisée, si cette mission n'a pas pu être accomplie à l'aide des fonctions WordPress, restez à l'écoute – j'y reviendrai vers la fin de l'article.

3. Appel de la fonction à partir d'un fichier modèle

Dans cette section, nous appellerons cette fonction à partir du fichier modèle que nous créerons pour cette catégorie spécifique.

Créons un fichier PHP en utilisant le slug de la catégorie (par exemple, si le slug de la catégorie est chat principal, alors le nom de notre fichier sera category-main-cat.php). Ce fichier sera utilisé par WordPress lorsque l'utilisateur accède à cette page de catégorie (voir les exemples de hiérarchie de modèles de catégorie ou la présentation visuelle de la hiérarchie de modèles).

Dans ce fichier, nous allons créer un

    élément dont les éléments de liste seront les sous-catégories.

    La prochaine étape sera de parcourir l'ensemble de données des sous-catégories que nous avons obtenues getChildCategoriesAndPostset affichez les données de ses publications. Mais avant de pouvoir le faire, nous devons créer une fonction qui extrait les informations de publication du $ posts tableau.

    4. Extrayons les informations de publication du $ posts Tableau

    Chaque itération sur une sous-catégorie aura une itération imbriquée sur les ID de publication qui lui appartiennent. Nous utiliserons cet identifiant de publication pour obtenir les informations pertinentes et les afficherons sous le nom de la sous-catégorie actuelle.
    Comment afficherons-nous les informations de chaque article en fonction de l'identifiant de l'article? Comme nous l'avons mentionné au début de l'article, le comportement par défaut de la page Catégorie est de récupérer les articles de la catégorie et de les stocker dans un tableau global appelé $ posts. Nous allons donc écrire une fonction à laquelle un identifiant de publication est passé, et elle extraira les informations de cette publication de la $ posts tableau en utilisant le array_filter () méthode. Une autre petite méthode que nous utiliserons est array_values ​​() – parce que depuis array_filter renvoie un élément du tableau mais pas nécessairement avec l'index 0, nous devons appeler array_values dont le travail consiste à renvoyer toutes les valeurs du tableau et indexer le tableau à partir de 0. Nous allons créer cette fonction dans le Catégories classe et nommez-la getCurrentPostFromCategoryList. Ensuite, nous l'appellerons à partir du fichier de modèle de notre catégorie principale, category-main-cat.php.

    Voici la fonction:

    function getCurrentPostFromCategoryList ($ post_id) 
    
        global $ posts;
        $ ret = null;
        $ curr_post = array_filter ($ posts, function ($ obj) use ($ post_id) 
            return $ obj-> ID == $ post_id;
        );
        $ curr_post = array_values ​​($ curr_post);
        if (count ($ curr_post)> 0) 
            $ ret = $ curr_post[0];
        
    
        return $ ret;
    

    Et maintenant, nous sommes prêts à l'utiliser.

    5. Afficher la liste de publications sous sa sous-catégorie respective

    Revenons à notre category-main-cat.php, nous allons créer un

  • élément, et y afficher les informations de publication respectives: le titre de la publication en tant que lien vers la publication réelle. Nous le ferons en utilisant un pour chaque boucle pour parcourir le tableau d'identifiants et appeler les éléments susmentionnés getCurrentPostFromCategoryList fonction.

    <li id ​​= "chat-term_id; ?> "class =" subcategory-category-wrapper closed ">
          

    Nom; ?>

      post_ids comme $ post_id) // assigne le post courant au $ post global, afin que le modèle puisse utiliser les fonctions de la boucle $ post = getCurrentPostFromCategoryList ($ post_id); ?> <? php le_titre (sprintf ('
    • ', esc_url (get_permalink ())),'
    • '); ?>
  • <! - # post- ->

    Nous avons donc obtenu une liste de publications affectées à leur sous-catégorie parente, avec une seule requête à la base de données.