Использование wp_query для запроса нескольких категорий с ограниченными сообщениями по категории?
-
16-10-2019 - |
Вопрос
У меня есть 3 категории с каждыми 15 постами, я хочу сделать один запрос на DB, принося только 5 первых постов для каждой категории, как я могу это сделать?
$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));
В случае, если это невозможно, что более эффективно, получая все посты для родительской категории и пробираясь через них или создавая 3 разных запроса?
Решение
То, что вы хотите, возможно, но потребует от вас вникнуть 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 Union с posts_join
Фильтр
Используя вышеизложенное, вы можете либо Просто сделайте звонок напрямую или вы можете использовать posts_join
фильтрный крючок Как следующее; Примечание я использую PHP Heredoc Так что будьте уверены SQL;
это слева. Также обратите внимание, что я использовал глобальный VAR, чтобы позволить вам определить категории за пределами крючка, перечислив категорию слизняков в массиве. Вы можете поместить этот код в плагин или в тему 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 Time 3, верно? Если это так, то, возможно, есть другие параметры, которые используют WordPress API?
Лучше использовать API Transients для кэширования?
Я предполагаю, что ваши сообщения не будут меняться часто, правильно? Что если вы принимаете три (3) запроса периодически, а затем кэшируйте результаты, используя Переходные API? Вы получите обслуживающий код и отличную производительность; немного лучше, чем 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
Filter Hook, который вам, вероятно, лучше предложите, используя кэширование с Переходные API вместо.
Надеюсь это поможет?
Другие советы
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
Теперь содержит первые пять постов для каждой категории.
Я не знаю способа получить первые пять постов для каждой из категорий в одном запросе. Если у вас когда -нибудь будет только 45 постов, то вы будете нажимать на базу данных один раз и получить пять постов для каждой категории, вероятно, является наиболее эффективным подходом. Нанести удар по базе данных три раза и объединение результатов не плохо.