En utilisant WP_Query à plusieurs requêtes Catégories RESTREINTE messages Catégorie par?

wordpress.stackexchange https://wordpress.stackexchange.com/questions/907

  •  16-10-2019
  •  | 
  •  

Question

J'ai 3 catégories avec chacun 15 postes, je veux faire une seule requête à la db apportant seulement 5 premiers messages pour chaque catégorie, comment puis-je faire?

$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));

Dans le cas où ce ne est pas possible, ce qui est plus efficace, obtenir tous les postes de la catégorie parente et en boucle à travers eux ou de créer 3 requêtes différentes?

Était-ce utile?

La solution

Ce que vous voulez est possible, mais il faudra que vous plonger dans SQL que je tiens à éviter autant que possible (pas parce que je ne sais pas, je suis une avance développeur SQL, mais parce que dans WordPress vous voulez utiliser l'API chaque fois que possible pour minimiser les problèmes de compatibilité des futurs liés aux changements de la structure de la base de données futures potentielles.)

SQL avec un opérateur UNION est possible

Pour utiliser SQL ce dont vous avez besoin est un opérateur UNION dans votre requête, quelque chose comme ceci en supposant que vos limaces de catégorie sont "category-1", "category-1" et "category-3":

SELECT * FROM wp_posts WHERE ID IN (
  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-1'
  LIMIT 5

  UNION

  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-2'
  LIMIT 5

  UNION

  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-3'
  LIMIT 5
)

Vous pouvez utiliser SQL UNION avec un filtre posts_join

En utilisant ce qui précède, vous pouvez soit juste faire l'appel directement ou vous pouvez utiliser un crochet de filtre posts_join comme la manière suivante; Je constate suis sur un PHP heredoc pour être sûr que le SQL; affleure gauche. Notez également que j'ai utilisé une variable globale pour vous permettre de définir les catégories en dehors du crochet en énumérant les limaces de catégorie dans un tableau. Vous pouvez mettre ce code dans un plug-in ou dans le fichier functions.php de votre thème:

<?php
global $top_5_for_each_category_join;
$top_5_for_each_category_join = array('category-1','category-2','category-3');
add_filter('posts_join','top_5_for_each_category_join',10,2);
function top_5_for_each_category_join($join,$query) {
  global $top_5_for_each_category_join;
  $unioned_selects = array();
  foreach($top_5_for_each_category_join as $category) {
    $unioned_selects[] =<<<SQL
SELECT object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='{$category}'
LIMIT 5
SQL;
  }
  $unioned_selects = implode("\n\nUNION\n\n",$unioned_selects);
  return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}

Mais il peut y avoir des effets secondaires

Bien sûr, utiliser les crochets de modification de requête comme posts_join invite toujours des effets secondaires en ce sens qu'ils agissent à l'échelle mondiale sur les requêtes et donc vous devez habituellement pour envelopper vos modifications dans un if qui utilise uniquement en cas de besoin et quels critères test peut être délicat.

Mise au point sur l'optimisation Au lieu de cela?

Cependant, je suppose que votre question porte sur plus sur l'optimisation que d'être capable de faire un top 5 fois 3 requête, non? Si tel est le cas, alors peut-être il y a d'autres options qui utilisent l'API de WordPress?

Il vaut mieux utiliser l'API pour Transitoires Mise en cache?

Je suppose que vos messages ne changeront pas que souvent, correct? Que faire si vous acceptez les trois (3) requête en demandant périodiquement et mettre en cache les résultats en utilisant Transitoires API ? Vous obtenez le code maintenable et d'excellentes performances; un bon peu mieux que la requête UNION ci-dessus parce que WordPress va stocker les listes de messages sous forme de tableau dans un enregistrement sérialisée de la table wp_options.

Vous pouvez prendre l'exemple suivant et déposez-les dans votre racine de site Web comme test.php pour tester ceci:

<?php

$timeout = 4; // 4 hours
$categories = array('category-1','category-2','category-3');

include "wp-load.php";
$category_posts = get_transient('top5_posts_per_category');
if (!is_array($category_posts) || count($category_posts)==0) {
  echo "Hello Every {$timeout} hours!";
  $category_posts = array();
  foreach($categories as $category) {
    $posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}");
    foreach($posts as $post) {
      $category_posts[$post->ID] = $post;
    }
  }
  set_transient('top5_posts_per_category',$category_posts,60*60*$timeout);
}
header('Content-Type:text/plain');
print_r($category_posts);

Résumé

Alors oui, vous pouvez faire ce que vous avez demandé l'aide d'une requête UNION SQL et vous êtes probablement mieux crochet filtre posts_join offre en utilisant la mise en cache avec Transitoires API à la place.

Hope this helps?

Autres conseils

WP_Query() ne supporte pas quelque chose comme First X pour chaque chat . Au lieu de WP_Query() vous pouvez utiliser get_posts() sur chacune de vos catégories, pour ainsi dire trois fois:

<?php
$posts      = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
  $posts[] = get_posts('numberposts=5&offset=1&category='.$cat);
}
?>

$posts contient maintenant les cinq premiers postes pour chaque catégorie.

Je ne sais pas d'un moyen d'obtenir les cinq premiers postes pour chacune des catégories dans une seule requête. Si vous allez jamais avoir seulement 45 postes, puis en appuyant la base de données une fois et obtenir vos cinq postes pour chaque catégorie est probablement l'approche la plus efficace. Frapper la base de données trois fois et en combinant les résultats ne sont pas une mauvaise chose cependant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à wordpress.stackexchange
scroll top