Фильтрация записей по нескольким таксономиям

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

У меня есть страница, на которой я хочу отображать все записи определенного типа, который мы будем называть “персоны”. Я хочу дать пользователю возможность фильтровать всех персон по нескольким (!) таксономиям: возраст, город, профессия, уровень опыта. Лучший способ сделать это — кликать по флажкам и получать результаты сразу через Ajax без перезагрузки страницы.

Думаю, это то, что многие разработчики WordPress хотят реализовать. К сожалению, я не нашел подходящего урока для достижения этого. Но это должно быть что-то простое для опытных разработчиков WordPress…

Может кто-нибудь предоставить шаблон кода для создания страницы фильтра для описанного выше пользовательского типа записи?

Я уже знаю, как фильтровать записи по только ОДНОЙ таксономии с помощью jQuery. Это код, который я использовал до сих пор:

<!-- ШАБЛОН СТРАНИЦЫ ДЛЯ ОБЗОРА ВСЕХ ЗАПИСЕЙ ТИПА "ПЕРСОНЫ" -->

        <!-- СПИСОК ВСЕХ ЗАПИСЕЙ ПО ТАКСОНОМИИ "ГОРОДА"  -->
        <div class="cities">

        <a href="#" id="all">Все города</a>             
        <?php
        // Получение всех терминов таксономии
        $taxonomy = 'cities';
        $terms = get_terms($taxonomy); 
        if ( $terms && !is_wp_error( $terms ) ) :
        foreach ( $terms as $term ) { ?>
            <a href="javascript:void(0);" data-target="<?php echo $term -> slug; ?>"><?php echo $term -> name; ?></a>
         <?php } endif; ?>

        </div>

        <!-- ВЫВОД ПЕРСОН -->

        <div class="overview_persons">

            <?php  
            $args= array(
                'post_type' => 'persons', 
                'post_status' => 'publish',
                'meta_key' => 'zip',
                'orderby' => 'meta_value_num',
                'order' => 'ASC',
                'posts_per_page' => -1
            );
            query_posts($args);

            if ( have_posts() ) : while ( have_posts() ) : the_post(); 

                $post_terms = wp_get_post_terms( $post->ID, $taxonomy, array( "fields" => "slugs" ) );
                $post_terms_space_separated = implode(" ", $post_terms);
                ?>

                <!-- вывод выбранного значения таксономии в класс div персоны -->
                <div class="person <?php echo $post_terms_space_separated; ?>">
                    <!-- описание персоны -->                          
                </div>                  

            <?php endwhile; endif; wp_reset_query(); ?>

        </div>

<!-- МОЙ JQUERY ДЛЯ ФИЛЬТРАЦИИ ПЕРСОН ПО ТАКСОНОМИИ "ГОРОД" -->
<script>
    jQuery(document).ready(function() {

        // Клик по городу 
        jQuery('a[data-target]').click(function() {
              jQuery('.person').show().not('.' + this.dataset.target).hide();

        });

        // Клик по "Все города"
        jQuery('#all').click(function(e) {
              e.preventDefault();
              jQuery('.person').show();

        });

    });

</script>

Этот код работает прекрасно. Но мой новый вызов — фильтрация персон по более чем одной таксономии — не только по городу, но также по возрасту, профессии и уровню опыта. Как необходимо изменить мой код для достижения этого? Конечно, предпочтительнее сделать это через Ajax.

Во-первых, вы должны использовать WP_Query вместо query_posts.

Обратите внимание на Параметры Таксономии.

Прежде всего tax_query и relation.

// Репост из указанной выше ссылки
   $args = array(
        'post_type' => 'post',
        'tax_query' => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'movie_genre',
                'field' => 'slug',
                'terms' => array( 'action', 'comedy' )
            ),
            array(
                'taxonomy' => 'actor',
                'field' => 'id',
                'terms' => array( 103, 115, 206 ),
                'operator' => 'NOT IN'
            )
        )
    );

ИЛИ, если вы предпочитаете задать его позже внутри цикла, изучите array_key_exists. Вы могли бы запустить цикл снова, но на этот раз проверять каждую запись на совпадение с термином.

// БОЛЬШЕ НЕ РАБОТАЕТ, WORDPRESS ИЗМЕНИЛ СТРУКТУРУ МАССИВА get_the_terms() -- ОКТЯБРЬ 2015
   /* if( array_key_exists( 111, get_the_terms($post->ID,'age') ) &&  array_key_exists( 222, get_the_terms($post->ID,'city') ) ) { 
      // вывод записи
    } */

ИЛИ, вы могли бы просто сделать это все на jQuery (например), если вы все равно будете загружать каждую запись на странице. Вы могли бы выводить data атрибуты для каждой записи, содержащие термины, которыми они помечены.

<!-- Например  // Где 111 и 222 относятся к id термина -->
<div class="person" data-age="id111" data-city="id222"></div>

И просто .hide() те, которые не соответствуют выбранным терминам для фильтрации.

Это не новый вопрос, однако сегодня мы не обязаны использовать jQuery и WP_Query для того, чтобы это работало.

Более того, в Темах Блока WordPress мы даже не можем использовать WP_Query для создания фильтра по таксономиям.

По моему мнению, нам нужно использовать следующее:

  • Блок Цикла Запроса (доступен как часть редактора сайта WordPress)
  • Интерактивный API (который позволяет сделать наш фильтр полностью AJAX)
  • Блок таксономического фильтра (который будет взаимодействовать как с Интерактивным API, так и с блоком цикла запроса и фильтровать для нас записи или пользовательские типы записей).

Поскольку первые две вещи доступны в WordPress по умолчанию в наши дни, нам нужен только блок таксономического фильтра, чтобы это работало для нас. Я бы рекомендовал взглянуть на этот: https://rudrastyh.com/plugins/taxonomy-filter-block.

.

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

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

Понимание задачи

У вас есть кастомный тип записи "persons" (персоны), где записи могут быть отфильтрованы по нескольким таксономиям: возраст, город, профессия, и уровень опыта. Идеальным решением было бы реализовать фильтрацию на сайте при помощи AJAX, чтобы избежать перезагрузки страницы, и позволить пользователям динамически видеть результаты.

Реализация с AJAX и WP_Query

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

Шаг 1: Настройка HTML

Вам необходимо создать чекбоксы для каждой таксономии. Например:

<div class="filters">
    <h3>Фильтры</h3>
    <div class="filter" id="age-filter">
        <h4>Возраст</h4>
        <?php 
            $terms = get_terms(['taxonomy' => 'age', 'hide_empty' => false]);
            foreach ($terms as $term) {
                echo '<label><input type="checkbox" name="age" value="' . esc_attr($term->slug) . '">' . esc_html($term->name) . '</label>';
            }
        ?>
    </div>
    <!-- Аналогично для других таксономий -->
</div>
<div id="persons-results"></div>

Шаг 2: JavaScript для обработки фильтрации

Используйте jQuery для отслеживания изменений в чекбоксах и отправки AJAX-запросов.

jQuery(document).ready(function($) {
    $('input[type="checkbox"]').change(function() {
        var filters = {};
        $('input[type="checkbox"]:checked').each(function() {
            var filterType = $(this).attr('name');
            if (!filters[filterType]) {
                filters[filterType] = [];
            }
            filters[filterType].push($(this).val());
        });

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'filter_persons',
                filters: filters
            },
            success: function(data) {
                $('#persons-results').html(data);
            }
        });
    });
});

Шаг 3: Обработка AJAX запроса в PHP

Добавьте обработчик в functions.php для обработки AJAX-запросов:

add_action('wp_ajax_filter_persons', 'filter_persons');
add_action('wp_ajax_nopriv_filter_persons', 'filter_persons');

function filter_persons() {
    $args = [
        'post_type' => 'persons',
        'posts_per_page' => -1,
        'tax_query' => ['relation' => 'AND']
    ];

    if (!empty($_POST['filters']['age'])) {
        $args['tax_query'][] = [
            'taxonomy' => 'age',
            'field' => 'slug',
            'terms' => $_POST['filters']['age']
        ];
    }
    // Повторите для других таксономий

    $query = new WP_Query($args);
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            echo '<div>' . get_the_title() . '</div>'; // Вывести нужную информацию
        }
    } else {
        echo 'Нет результатов.';
    }
    wp_die();
}

Современный подход: Использование Блочного Редактора и API Interactivity

С переходом WordPress на блочный редактор (Gutenberg), появилась возможность использовать Query Loop block и Interactivity API для достижения тех же целей модным образом. Это позволяет создавать интерактивные интерфейсы, минимизируя написание кастомного кода. Подумайте о создании блоков, которые будут взаимодействовать друг с другом по API – это современный, но несколько более сложный подход для выполнения такой задачи.

Для пользователей, еще не знакомых с Interactivity API, рекомендую ознакомиться с соответствующей документацией и начинать изучение с простого примера блока с таксономическим фильтром, таким как тот, что предлагается на rudrastyh.com.

Используя эти методы, вы сможете создать мощный и функциональный интерфейс фильтрации постов в WordPress, который будет удобен в использовании и интерпретируем редакторами WordPress.

Это изменение не только улучшит пользовательский опыт, но и увеличит производительность вашего веб-сайта.

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

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