фильтр pre_get_post возвращает результаты, когда этого не должно быть

Вопрос или проблема

Я пытаюсь фильтровать пользовательский тип записи (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;
    }
}

Объяснение изменений

  1. Использование empty($post_ids): Теперь код проверяет, есть ли элементы в массиве $post_ids. Если массив пуст, условие будет истинным, и мы можем задать параметры для запроса, чтобы показать сообщение "Нет результатов".

  2. Установка post__in: Если массив не пустой, мы добавляем найденные ID постов в параметр post__in. Если пустой, устанавливаем post__in равным массиву, содержащему несуществующий ID поста (array(0)), что позволит WordPress возвращать "Нет результатов".

  3. Читаемость и SEO: Использование явных и коротких условий позволяет коду быть более понятным. Запись также подразумевает, что ваш плагин корректно обрабатывает пользовательские типы записей и возвращает значимые сообщения пользователю, что положительно сказывается на SEO.

Заключение

Корректная проверка массива и логика фильтрации сделают ваш код более устойчивым к ошибкам и улучшат взаимодействие с пользователями. Убедитесь, что весь остальной код плагина также соответствует этим принципам, чтобы поддерживать его высокое качество.

Оцените материал
Добавить комментарий

Капча загружается...