web-dev-qa-db-fra.com

Avec une WP_Query, comment puis-je obtenir une liste de balises?

J'ai un new WP_Query que j'utilise pour générer une boucle personnalisée et afficher un ensemble de publications. Une des choses que fait la requête est de fournir une pagination.

Avant d’afficher les articles demandés, j’aimerais obtenir une liste de tous les tags pour les articles trouvés. Je sais que je peux le faire en parcourant chacun des messages, puis en supprimant les doublons, mais j'espérais une approche plus élégante.

3
Jack

Je ne pense pas que ce soit possible. La requête SQL effectuée par WP_Query renvoie uniquement les objets de publication (et peut-être des métadonnées), tandis que les balises résident dans une autre table. Lorsque vous parcourez les publications renvoyées dans les modèles, vous mettez généralement the_tags(); ou quelque chose de similaire dans vos modèles, qui exécute à son tour une nouvelle requête de base de données pour chaque publication.

Cependant, vous pouvez exécuter une requête distincte pour charger les balises avant d'exécuter votre requête de publications principales. Autant que je sache, il n'y a pas de fonction API WordPress qui vous permettra de charger les tags de plus d'un message à la fois, mais vous pouvez le faire en appelant directement $wpdb.

Quelque chose comme cela pourrait vous aider à démarrer:

global $wpdb;
$sql = $wpdb->prepare(
    "SELECT DISTINCT $wbdb->terms.* FROM $wbdb->term_relationships
        JOIN $wbdb->posts
            ON $wbdb->posts.ID = $wbdb->term_relationships.object_id
        JOIN $wbdb->term_taxonomy
            ON $wbdb->term_taxonomy.term_taxonomy_id = $wbdb->term_taxonomy.term_taxonomy_id
        JOIN $wbdb->terms
            ON $wbdb->term_taxonomy.term_id = $wbdb->terms.term_id
        WHERE $wbdb->term_taxonomy.taxonomy = 'post_tag'
            AND $wbdb->posts.ID IN (1,2,3,4,5,6,7,8,9,10)"
);
$tags = $wpdb->query($sql);

Comme vous pouvez le constater, cela suppose que vous connaissez à l'avance vos identifiants de publication, ce que vous ne connaissez probablement pas. Dans ce cas, vous devrez remplacer les listes entre parenthèses par une sous-requête, qui dans sa forme la plus simple serait SELECT ID FROM $wpdb->posts, mais il faudra probablement filtrer/ordonner/limiter les publications par catégorie, date, etc. Un problème que j'ai rencontré est que ma version de MySQL ne supportait pas LIMIT dans les sous-requêtes. Si le vôtre ne le fait pas non plus, il pourrait être difficile de le faire en une seule requête. Sauf si vous avez beaucoup de publications, vous pouvez simplement parcourir votre WP_Query et collecter les identifiants de publication. Dans tous les cas, cela sera plus rapide que d'exécuter des requêtes distinctes pour chaque publication, car vous n'exécuterez qu'une seule requête liée aux balises au lieu d'en exécuter une pour chaque publication.

1
Simon

Par souci de postérité, j'ai fini par parcourir deux fois la boucle: une fois pour obtenir les balises, puis pour afficher la page.

Voici mon code:

if ( have_posts() ) :
 // get tags for found posts
 $recent_tags = array();
 while ( $loop->have_posts() ) : $loop->the_post();
  foreach(get_the_tags() as $t) $recent_tags[$t->slug] = $t->name; // this adds to the array in the form ['slug']=>'name'
 endwhile; 

 // de-dupe
 $recent_tags = array_unique($recent_tags);
 // sort
 natcasesort($recent_tags);

 // do something with the array

 while ( $loop->have_posts() ) : $loop->the_post();

 // normal wp loop
2
Jack

Vous pouvez obtenir les tags de plusieurs publications en passant 'object_ids' à get_terms() .

Tout d’abord, laissez un autre WP_Query vous renvoyer uniquement les identifiants de vos publications souhaitées. Par exemple, obtenez tous les messages d'une catégorie donnée:

// Get the posts.
$category = get_queried_object();
$args = [
  'cat'    => $category->term_id,
  'fields' => 'ids',
];
$the_query = new WP_Query($args);

Maintenant que vous avez les identifiants, vous pouvez simplement les transmettre à get_terms() et une liste de toutes les balises de ces publications sélectionnées vous sera renvoyée:

// Get the terms of these posts.
if ($the_query->have_posts()) {
  $terms = get_terms([
    'taxonomy' => 'post_tag',
    'object_ids' => $the_query->posts,
  ]);
}

Source: https://developer.wordpress.org/reference/classes/wp_term_query/__construct/#comment-2500

0
leymannx