Вопрос или проблема
Я пытаюсь фильтровать пользовательский тип записи (CPT) по массиву идентификаторов записей, используя фильтр pre_get_post в своем плагине. Все работает хорошо, когда есть записи, соответствующие идентификаторам, но когда записей, соответствующих идентификаторам, нет, я получаю все записи в CPT, которые я пытаюсь отфильтровать в ответ. Что мне нужно, если идентификаторы записей не найдены (или записи из идентификаторов записей), это чтобы страница архива отображала обычное сообщение ‘результатов не найдено’.
Вот краткое содержание моего скрипта…
add_action('pre_get_posts', array(__CLASS__, 'get_posts')); // запускается внутри класса
function get_posts($wp_query) {
if ($wp_query->is_main_query() && !is_admin() && is_post_type_archive(MbeEnrollments::MBE_POST_TYPE_NAME) && $wp_query->query_vars['list-view'] == 'list-view') {
//Для целей этого примера я убрал скрипт в разделе, который генерирует идентификаторы записей CPT, которые я пытаюсь вернуть. Эта часть работает хорошо и как ожидалось.
//если идентификаторы записей найдены
if ($post_ids) {
$wp_query->set('post__in', $post_ids);
}
return;
}
}
Я предполагаю, что проблема в том, что страница архива CPT будет работать как обычно, если моя if($post_ids)
условие вернет false. Однако я пытаюсь найти способ сделать так, чтобы это возвращалось без результатов. Спасибо заранее за любую помощь.
ОБНОВЛЕНИЕ:
Если я включаю идентификатор записи, который я знаю, что не существует в CPT, я получаю желаемое ‘Нет результатов’. Хотя это работает, это кажется немного хитрым и должно быть более аккуратный способ. Есть идеи?
Вот условие, которое работает….
if ($post_ids) {
$wp_query->set('post__in', $post_ids);
}else{//если нет идентификаторов записей, то передайте фейковый идентификатор записи, чтобы получить 'нет результатов'
$wp_query->set('post__in', array(0));
}
return;
Предполагая, что вы получаете пустой массив для $post_ids
, если нет совпадающих записей, я думаю, что это неправильно:
if ( $post_ids ) {}
Потому что массив существует, но он пустой. Попробуйте проверить на пустой массив:
if ( ! empty( $post_ids ) ) {}
$query->set( 'post__in', $post_ids );
Эта строка отвечает за применение фильтров к запросу.
Но вы используете ее ТОЛЬКО когда $post_ids истинно. Это означает, что когда $post_ids дает false, вы не фильтруете.
По сути, вы говорите:
if ($post_ids) { // если есть значения для фильтрации
$wp_query->set('post__in', $post_ids); // тогда используйте их для фильтрации
} // в противном случае не фильтруйте.
return;
Так что просто убедитесь, что $post_ids всегда массив, даже пустой.
Затем не устанавливайте условно запрос.
Ответ или решение
Проблема, с которой вы столкнулись, заключается в том, что фильтр pre_get_posts
неправильно обрабатывает случай, когда массив ID записей ($post_ids
) пуст или не содержит совпадающих записей. Давайте рассмотрим, как это можно исправить и сделать ваш код более надежным.
Суть проблемы
Ваш оригинальный код проверяет условие if ($post_ids)
, что будет истинным, только если массив $post_ids
содержит хотя бы одно значение. Однако если массив существует, но пустой, код будет продолжать выполняться, и ваша сортировка не будет применена, что приведет к выводу всех записей вашего пользовательского типа записи (Custom Post Type, CPT).
Решение
Здесь необходимо изменить логику проверки массива, чтобы корректно обрабатывать как непустые массивы, так и пустые. Это можно сделать, используя функцию empty()
, которая пройдет проверку и на случай, если массив пустой.
Также, вместо того чтобы не применять фильтры, мы можем явно установить условие, чтобы выводить сообщение "Нет результатов", если массив $post_ids
пуст.
Исправленный код
Вот как мог бы выглядеть исправленный код:
add_action('pre_get_posts', array(__CLASS__, 'get_posts')); //вызывается внутри класса
function get_posts($wp_query) {
if ($wp_query->is_main_query() && !is_admin() && is_post_type_archive(MbeEnrollments::MBE_POST_TYPE_NAME) && $wp_query->query_vars['list-view'] == 'list-view') {
// Предполагается, что здесь будет логика для получения постов
// $post_ids = ...;
// Проверка на пустой массив
if (!empty($post_ids)) {
$wp_query->set('post__in', $post_ids);
} else {
// Если массив пустой, устанавливаем условие, чтобы вернуть "нет результатов"
$wp_query->set('post__in', array(0)); // ID, не существующего поста
}
return;
}
}
Объяснение изменений
-
Использование
empty($post_ids)
: Теперь код проверяет, есть ли элементы в массиве$post_ids
. Если массив пуст, условие будет истинным, и мы можем задать параметры для запроса, чтобы показать сообщение "Нет результатов". -
Установка
post__in
: Если массив не пустой, мы добавляем найденные ID постов в параметрpost__in
. Если пустой, устанавливаемpost__in
равным массиву, содержащему несуществующий ID поста (array(0)
), что позволит WordPress возвращать "Нет результатов". -
Читаемость и SEO: Использование явных и коротких условий позволяет коду быть более понятным. Запись также подразумевает, что ваш плагин корректно обрабатывает пользовательские типы записей и возвращает значимые сообщения пользователю, что положительно сказывается на SEO.
Заключение
Корректная проверка массива и логика фильтрации сделают ваш код более устойчивым к ошибкам и улучшат взаимодействие с пользователями. Убедитесь, что весь остальной код плагина также соответствует этим принципам, чтобы поддерживать его высокое качество.