Диагностика проблемы: почему стандартный запрос WordPress не всегда подходит
По умолчанию WordPress выводит на страницах архивов, категорий или главной только опубликованные записи с пост-статусом publish. Однако часто требуется изменить выборку: показать черновики, отложенные записи, записи определённого типа или с дополнительными условиями. Стандартные параметры через настройки или виджеты не всегда позволяют это сделать без кода.
Если вам нужно изменить логику выборки записей без создания отдельных WP_Query, то правильный способ — использовать фильтр pre_get_posts. Он позволяет модифицировать основной запрос WordPress до его выполнения.
Пошаговое решение: как изменить post_status через pre_get_posts
Шаг 1. Подключите хук в functions.php вашей темы или в плагине
add_action('pre_get_posts', 'custom_modify_main_query');
function custom_modify_main_query($query) {
// Убедимся, что мы в главном запросе на фронтэнде
if (is_admin() || !$query->is_main_query()) {
return;
}
// Пример: показать также черновики на главной
if (is_home()) {
$query->set('post_status', array('publish', 'draft'));
}
}Шаг 2. Подберите условия для нужных страниц и типов записей
Вы можете проверять:
is_home()— главная страница блогаis_post_type_archive('product')— архив кастомного типа записиis_category('news')— категория по имени или ID
Например, чтобы вывести на странице архива кастомного типа записи product только опубликованные и отложенные (future) товары:
add_action('pre_get_posts', 'modify_product_archive_query');
function modify_product_archive_query($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_post_type_archive('product')) {
$query->set('post_status', array('publish', 'future'));
}
}Как проверить, что решение сработало
1. Откройте соответствующую страницу сайта. Например, главную или архив.
2. Если выводятся записи с нужным статусом (например, черновики или отложенные), значит фильтр работает.
3. Для более точной проверки можно временно включить отладку и вывести SQL-запрос:
add_action('pre_get_posts', function($query) {
if (is_admin() || !$query->is_main_query()) return;
if (is_home()) {
$query->set('post_status', array('publish', 'draft'));
add_action('shutdown', function() use ($query) {
global $wpdb;
error_log($query->request); // SQL-запрос в лог
});
}
});Частые ошибки при использовании pre_get_posts для изменения post_status
- Изменение в админке без проверки
is_admin(): приводит к сбоям и неправильной работе интерфейса. - Не проверяется
is_main_query(): влияет на все запросы, включая второстепенные и виджеты, что может вызвать неожиданные результаты. - Установка одного статуса как строки вместо массива: например,
'draft,publish'— это неправильный формат, нужен массивarray('draft', 'publish'). - Забывают задать условие, и фильтр применяет изменения на всех страницах: это может нарушить логику сайта.
Практические советы по безопасности и производительности
- Всегда ограничивайте область действия фильтра проверками
is_main_query()и!is_admin(), чтобы не влиять на административную часть. - Избегайте сложных и ресурсоёмких условий в
pre_get_posts, чтобы не замедлять загрузку страниц. - Если нужно сложное кэширование, используйте Transients API для хранения результатов запросов с кастомным статусом.
- Регулярно проверяйте, что новые статусы не нарушают логику плагинов SEO и кэширования.
Сравнение способов изменения выборки по post_status
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Изменение WP_Query напрямую | Гибко, для кастомных запросов | Не влияет на основной запрос | Новые запросы в шаблонах |
Фильтр pre_get_posts | Изменяет основной запрос, универсально | Нужно аккуратно проверять условия | Изменение вывода стандартных страниц |
| Плагины для управления статусами | Простота настройки без кода | Может быть избыточно, конфликты | Для пользователей без навыков PHP |