Фильтрация постов в подкатегории не работает.

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

Фильтрация постов в подкатегориях не работает

/category/child-category-1/filter_xxx-yyy/ – РАБОТАЕТ

/category/child-category-1/child-category-2/filter_xxx-yyy/ – НЕ работает

/category/child-category-1/child-category-2/child-category-3/filter_xxx-yyy/ – НЕ работает

            add_action('pre_get_posts', array($this, 'filter_posts_by_custom_fields'));
        add_action('init', array($this, 'register_rewrite_rules'));
        
    public function register_rewrite_rules() {
        add_rewrite_rule('^category/([^/]+)/(.+)/?$', 'index.php?category_name=$matches[1]&custom_filter=$matches[2]', 'top');
        add_rewrite_tag('%custom_filter%', '([^&]+)');
    }

public function filter_posts_by_custom_fields($query) { 
    if (!$query->is_main_query() || !is_category() || !$query->get('custom_filter')) return;

    $custom_filter = $query->get('custom_filter');
    $filters = explode('-and-', $custom_filter);

    $meta_query = ['relation' => 'AND'];
    foreach ($filters as $filter) {
        if (strpos($filter, 'filter_') === 0) {
            list($key, $value) = explode('-', $filter, 2);

            $values = explode('-plus-', $value);

            $meta_query[] = [
                'key' => $key,
                'value' => count($values) > 1 ? $values : $value,
                'compare' => count($values) > 1 ? 'IN' : '='
            ];
        }
    }
    $query->set('meta_query', $meta_query);
}

Как я могу сделать фильтр работающим на всех уровнях категорий?

Извините за мой английский.

Ответ или решение

Для решения проблемы с фильтрацией постов в дочерних категориях в WordPress, необходимо разобраться в коде, который отвечает за обработку пользовательских фильтров и перезапись правил URL. Правильная реализация этих компонентов обеспечит корректную работу фильтрации на всех уровнях иерархии категорий.

Анализ текущего кода

В вашем коде уже предусмотрены необходимые действия для фильтрации. Действие pre_get_posts отвечает за модификацию основного запроса, а init занимается регистрацией правил перезаписи.

  1. Регистрация правил перезаписи:

    add_rewrite_rule('^category/([^/]+)/(.+)/?$', 'index.php?category_name=$matches[1]&custom_filter=$matches[2]', 'top');
    add_rewrite_tag('%custom_filter%', '([^&]+)');

    Здесь вы регистрируете правило, которое обрабатывает URL вида /category/дочерняя-категория/filter_xxx-yyy/. Однако, для обеспечения работы фильтров в более глубоких вложенных категориях необходимо отказаться от жёсткой привязки к одному уровню.

  2. Фильтрация постов по пользовательским полям:

    public function filter_posts_by_custom_fields($query) { 
        if (!$query->is_main_query() || !is_category() || !$query->get('custom_filter')) return;
    
        $custom_filter = $query->get('custom_filter');
        // Логика обработки фильтров
    }

    В этом методе выполняется проверка текущего запроса и наличие пользовательского фильтра. Однако, из-за проверки на is_category(), фильтры могут не применяться для более глубоких уровней категории.

Рекомендации по исправлению

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

  1. Обновление правил перезаписи:
    Нужно обновить правило, чтобы оно корректно обрабатывало категории любой вложенности. Используйте следующую конструкцию для обработки произвольного количества уровней категорий:

    add_rewrite_rule('^category/(.+?)/(.+)/?$', 'index.php?category_name=$matches[1]&custom_filter=$matches[2]', 'top');

    В данной записи используется регулярное выражение (.+?), которое позволяет захватывать категорию, включая вложенные категории.

  2. Изменения в фильтрации постов:
    Измените условие проверки, чтобы оно учитывало и вложенные категории:

    public function filter_posts_by_custom_fields($query) { 
        if (!$query->is_main_query() || !is_category() || !isset($query->query_vars['custom_filter'])) return;
    
        $custom_filter = $query->get('custom_filter');
        // Логика обработки фильтров
    }

    В этом фрагменте важно использовать isset(), чтобы избежать потенциальных ошибок, если ключа custom_filter нет в массиве query_vars.

  3. Тестирование и очистка кэша:
    После внесения изменений не забудьте протестировать все возможные URL и выполнить обновление постоянных ссылок в админ-панели WordPress (Настройки -> Постоянные ссылки). Это потребуется для сброса кэша правил перезаписи.

Заключение

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

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

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