Получить последние записи всех категорий в одном запросе
Мой блог на WordPress имеет 12 категорий и 80 подкатегорий.
Мне нужно получить последние записи из каждой из этих 12 категорий.
Я знаю, как сделать это с помощью 12 запросов get_posts(), но есть ли способ получить их одним запросом?
Я пробовал сделать так, но этот код получает больше чем 12 записей:
// Получаем массив категорий (только первого уровня)
$cats= array();
$categories=get_categories($args);
foreach($categories as $category) {
if ($category->parent == 0) {
$cats[]= $category->term_id ;
}
}
$categories= implode(',',$cats);
// Получаем последнюю запись каждой категории
global $wpdb;
$querystr = "SELECT wposts.*
FROM $wpdb->posts wposts
LEFT JOIN $wpdb->term_relationships ON (wposts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->term_taxonomy.term_id IN($categories)
ORDER BY wposts.post_date DESC";
$pageposts = $wpdb->get_results($querystr, OBJECT);
И затем цикл:
global $post;
foreach ($pageposts as $k=>$post):
setup_postdata($post);
// ... стандартный цикл WordPress для вывода результатов
}
Количество запросов — не единственный показатель производительности. Один сложный запрос может быть дороже множества простых.
Стоимость (12 маленьких запросов) < стоимость 1 большого запроса + обработка строк/массивов.
Лучше выполнить 12 отдельных запросов. Если это ресурсоемко, сохраните результат в transient для последующего использования и экономии ресурсов.
Но еще лучше обновлять значения с помощью хука save_post, чтобы избежать необходимости "поиска" — операция сведется к простому получению сохраненного значения. Если хранить и получать его через get_option, дополнительные запросы не выполнятся, так как WordPress уже загрузил значение и не будет делать лишний SQL-запрос для повторного получения.
// в functions.php
function check_category_latest($post_id){
// проверяем категории, к которым относится пост
// для каждой назначенной категории
// если это последний пост в категории
set_option('mytheme_cat_'.$term_id,$post_id);
}
add_hook('save_post','check_category_latest');
// в месте вывода постов
$categories=get_categories($args);
foreach($categories as $category) {
$post_id = get_option('mytheme_cat_'.$category->term_id);
// вывод поста
}
Подобный подход даст желаемый результат для всех подкатегорий, при этом он будет значительно дешевле 12 отдельных запросов или даже одного сложного.
