1. Получить ID постов в конкретной категории:
$args = array(
'post_type' => 'post', // изолируем нужный post type
'post_status' => 'publish', // изолируем только опубликованные записи
'category__in' => array( 15 ), // где 15 - ID вашей категории
'posts_per_page' => -1, // забираем все посты, отвечающие требованиям
'fields' => 'ids', // возвращаем только массив ID найденных записей
'cache_results' => true, // кешируем полученные результаты
'no_found_rows' => true, // не считаем общее количество найденных записей
'update_post_meta_cache' => false, // не забираем и не кешируем метаданные для этих записей
'update_post_term_cache' => false, // не забираем и не кешируем термины для этих записей
);
$posts_in_category = new WP_Query( $args );
Половина $args - это оптимизация и ускорение запроса. Получаем только необходимые данные, не запрашиваем, не обрабатываем и не кешируем то, что нам вообще не нужно. Задача - получить и закешировать только массив ID записей, которые имеют нужную категорию. Все это
есть в документации.
2. Получаем теги, которые используются данными постами (полученными выше):
$args = array(
'taxonomy' => 'post_tag', // изолируем нужную таксономию
'object_ids' => $posts_in_category->posts, // получаем только теги, которые присвоеные объектам с этими ID
'update_term_meta_cache' => false, // true|false - получать ли (и кешировать ли) метаданные терминов
);
$tags_in_posts = get_terms( $args );
На выходе у вас будет массив тегов. Дополнительные параметры можете
смотреть тут. Собственно, вместо
get_terms() можете использовать
WP_Term_Query.
UPDATE:
Допустил ошибку в коде, строчка
'object_ids' => $posts_in_category,
должна быть
'object_ids' => $posts_in_category->posts,
- ибо переменная будет содержать объект WP_Query, а уже свойство posts будет содержать ID найденных постов.
Еще один важный нюанс и еще одна ошибка - если категорию включать с помощью параметра 'cat', то запрос по умолчанию будет выполнен с параметром 'include_children' => true, что нам не нужно, ибо исказит результат и включит ненужные посты. Переписал и этот фрагмент - вместо использования стандартного параметра 'cat' теперь используем 'category__in' - это включит только посты, которым назначена именно эта категория.
Что касается количества выполненных запросов:
WP_Query выполнит только 1 запрос:
SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (2) )
AND wp_posts.post_type = 'post'
AND ((wp_posts.post_status = 'publish'))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
В данном коде 2 = ID категории на моем тестовом сайте. На выходе получается Х постов, которым назначена именно эта категория.
Далее, get_terms выполнит тоже всего 1 запрос:
SELECT t.*, tt.*
FROM wp_terms AS t
INNER JOIN wp_term_taxonomy AS tt
ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships AS tr
ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.taxonomy IN ('post_tag')
AND tr.object_id IN (19, 15, 13, 1)
ORDER BY t.name ASC
В данном коде 19, 15, 13, 1 - это и есть ID постов, которые мы получили первым запросом. Таким образом, будут получены только термины таксономии post_tag, которые назначены этим конкретным постам.