Использование WP-запроса для запроса нескольких категорий с ограниченным количеством сообщений В каждой категории?


У меня 3 категории по 15 постов, я хочу сделать ОДИН запрос в бд, в результате чего для каждой категории будет только 5 первых постов, как я могу это сделать?

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

В случае, если это невозможно, что более эффективно, получить все сообщения для родительской категории и просмотреть их или создать 3 разных запроса?

Author: MikeSchinkel, 2010-08-25

3 answers

То, что вы хотите, возможно, но потребует от вас углубиться в SQL, которого я предпочитаю избегать, когда это возможно (не потому, что я этого не знаю, я продвинутый разработчик SQL, но потому, что в WordPress вы хотите использовать API, когда это возможно, чтобы минимизировать будущие проблемы совместимости, связанные с будущими потенциальными изменениями структуры базы данных.)

SQL с оператором UNION - это возможность

Для использования SQL вам нужен оператор UNION в вашем запросе, что-то вроде этого, предполагая, что ваши слизни категории "category-1", "category-1" и "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
)

Вы можете использовать ОБЪЕДИНЕНИЕ SQL с фильтром posts_join

Используя вышеизложенное, вы можете либо просто позвонить напрямую , либо вы можете использовать posts_join фильтр, как показано ниже; обратите внимание, что я использую PHP наследственный код поэтому убедитесь, что SQL; находится слева. Также обратите внимание, что я использовал глобальную переменную, чтобы вы могли определять категории за пределами крючка, перечисляя категории слизней в массив. Вы можете поместить этот код в плагин или в файл вашей темы functions.php:

<?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 " ;
}

Но Могут Быть Побочные эффекты

Конечно, использование крючков модификации запросов, таких как posts_join, всегда вызывает побочные эффекты, поскольку они действуют глобально на запросы, и поэтому вам обычно нужно обернуть свои изменения в if, который использует их только при необходимости, и какие критерии для проверки могут быть сложными.

Вместо этого сосредоточьтесь на оптимизации?

Тем не менее, я предполагаю, что ваш вопрос беспокоит больше оптимизация , чем возможность выполнить запрос 5 раз в 3 раза, верно? Если это так, то, может быть, есть другие варианты, использующие API WordPress?

Лучше использовать API переходных процессов для кэширования?

Я предполагаю, что ваши посты не будут меняться так часто, верно? Что делать, если вы периодически принимаете три (3) запроса, а затем кэшируете результаты с помощью API переходных процессов? Вы получите поддерживаемый код и отличную производительность; a намного лучше, чем запрос UNION выше, потому что WordPress будет хранить списки сообщений в виде сериализованного массива в одной записи таблицы wp_options.

Вы можете взять следующий пример и зайти в корневой каталог вашего веб-сайта как test.php, чтобы проверить это:

<?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);

Краткое описание

Хотя да, вы можете сделать то, что просили, используя запрос SQL UNION и крючок фильтра posts_join, вам, вероятно, лучше предложить использовать кэширование с API переходных процессов вместо этого.

Надеюсь, это поможет?

 16
Author: MikeSchinkel, 2014-09-06 22:23:39

WP_Query() не поддерживает что-то вроде Первого X Для каждой кошки. Вместо WP_Query() вы можете использовать get_posts() в каждой из ваших категорий, так сказать, три раза:

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

$posts теперь содержит первые пять сообщений для каждой категории.

 1
Author: hakre, 2010-08-25 20:54:06

Я не знаю способа получить первые пять сообщений для каждой из категорий в одном запросе. Если у вас когда-нибудь будет только 45 сообщений, то, вероятно, наиболее эффективным подходом будет один раз зайти в базу данных и получить пять сообщений для каждой категории. Однако трижды попасть в базу данных и объединить результаты - это не так уж плохо.

 0
Author: Bernard Chen, 2010-08-25 20:38:26