Диагностика проблемы: почему нужно исключать типы записей из главного запроса
При создании пользовательских типов записей (custom post types) в WordPress часто возникает необходимость исключить их из главного запроса на страницах блога или архивах. Если этого не сделать, на главной странице или в ленте новостей могут отображаться записи, которые не должны там показываться, например, портфолио, товары WooCommerce или отзывы.
Проверить, включены ли нежелательные типы записей в главный запрос, можно с помощью простого вывода типов в цикле. Для этого временно добавьте следующий код в файл functions.php вашей темы или в плагин:
add_action('pre_get_posts', function($query) {
if ($query->is_main_query() && !is_admin()) {
error_log(print_r($query->query_vars, true));
}
});После обновления страницы в логах будет видно, какие параметры запроса используются — в частности, параметр post_type. Если там указан массив с несколькими типами записей, и среди них есть те, что нужно исключить, значит задача актуальна.
Пошаговое решение: как исключить типы записей с помощью pre_get_posts
1. Определите, где именно хотите исключить типы записей
Чаще всего исключение нужно для главной страницы блога (is_home()) или для архивов определённого типа (is_archive()), а также для главного запроса (is_main_query()) — чтобы не ломать админку или дополнительные WP_Query.
2. Добавьте фильтр в functions.php или плагин
add_action('pre_get_posts', function($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_home() || $query->is_archive()) {
// Получаем текущий параметр post_type
$post_types = $query->get('post_type');
if (empty($post_types)) {
// По умолчанию это 'post'
$post_types = ['post'];
} elseif (!is_array($post_types)) {
$post_types = [$post_types];
}
// Типы записей, которые нужно исключить
$excluded = ['portfolio', 'product', 'testimonial'];
// Убираем исключаемые типы
$post_types = array_diff($post_types, $excluded);
// Если после исключения пусто, ставим 'post' по умолчанию
if (empty($post_types)) {
$post_types = ['post'];
}
// Обновляем параметр запроса
$query->set('post_type', $post_types);
}
});3. Проверьте работу фильтра
Очистите кэш сайта и браузера, затем откройте главную страницу блога и архивы. Записи типов, указанных в массиве $excluded, не должны отображаться.
Для дополнительной проверки можно временно добавить вывод в лог текущего параметра post_type прямо в фильтре:
error_log('Post types in query: ' . print_r($query->get('post_type'), true));Проверьте логи сервера или используйте плагин Debug Bar.
Частые ошибки и как их исправить
- Фильтр срабатывает в админке — забудьте добавить проверку
is_admin()иis_main_query(). Это приводит к нарушению функционала в админке. - Параметр post_type установлен в строку, а не массив — нужно всегда приводить к массиву перед исключением, иначе
array_diffне сработает корректно. - После исключения массив пустой — WordPress может не показать записи. В этом случае обязательно установите хотя бы один тип по умолчанию, например
post. - Забыли очистить кэш — результаты не обновятся до очистки кеша плагинов и браузера.
Проверка результата после внедрения
Чтобы убедиться, что фильтр работает:
- Откройте главную страницу блога и убедитесь, что записи из исключённых типов не показываются.
- Перейдите на архивные страницы, если применимо, и проверьте аналогично.
- Включите вывод параметра
post_typeв лог и убедитесь, что исключённые типы отсутствуют в запросе. - Проверьте, что в админке все записи доступны и ничего не сломалось.
Практические советы по производительности и безопасности
- Добавляйте фильтр только для главного запроса, чтобы не влиять на пользовательские WP_Query и админку.
- Избегайте жёстко прописанных типов записей — лучше вынести список исключаемых типов в отдельную опцию или константу.
- Если исключаете типы записей WooCommerce (
product), убедитесь, что это не нарушит работу связанных функций и виджетов.
Сравнение вариантов решения
| Метод | Плюсы | Минусы |
|---|---|---|
| pre_get_posts | Гибкий контроль, работает на уровне запроса, не требует сторонних плагинов | Нужно аккуратно фильтровать, чтобы не сломать админку или другие WP_Query |
| Использование плагинов фильтрации контента | Интуитивный интерфейс, меньше кода | Нагрузка на сайт, меньше гибкости, не всегда подходит для точечного исключения |
| Редактирование шаблонов темы (условные теги) | Простота для простых случаев | Небольшая гибкость, дублирование кода, не масштабируемо |