При разработке плагинов WordPress часто возникает задача организовать фильтрацию контента по таксономиям — например, по странам и городам, категориям и подкатегориям, типам и подтипам недвижимости. Простая фильтрация по терминам в таких случаях не подходит: таксономии иерархические, а значит, между терминами существуют связи “родитель → потомок”. В этой статье разберём, как реализовать иерархическую фильтрацию по таксономии в WordPress с помощью кастомной функции, которая корректно обрабатывает древовидные структуры.
Зачем нужна иерархическая фильтрация
Стандартная функция get_terms() позволяет получить список терминов таксономии, но выводит их “плоским” списком — без указания вложенности. Для удобства пользователя фильтр должен отображать дочерние термины с визуальным смещением или префиксом, чтобы различать, где родитель, а где дочерний элемент.
Например:
Молдова
– Кишинёв
Россия
– Москва
Такая структура помогает пользователю понимать, что “Кишинёв” относится к “Молдове”, а “Москва” — к “России”.
Создание функции для получения иерархических терминов
Для реализации иерархической фильтрации создадим специальную функцию в классе плагина — get_terms_hierarchical().
Она будет рекурсивно проходить по всем терминам, формируя вложенные <option> для тега <select>.
Пример структуры функции:
public function get_terms_hierarchical( $taxonomy, $current = 0, $parent = 0, $prefix = '' ) {
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
'parent' => $parent
]);
if ( !empty($terms) && !is_wp_error($terms) ) {
foreach ( $terms as $term ) {
$selected = ($current == $term->term_id) ? 'selected' : '';
echo '<option value="' . esc_attr($term->term_id) . '" ' . $selected . '>';
echo esc_html($prefix . $term->name);
echo '</option>';
// Рекурсия: получаем дочерние элементы
$this->get_terms_hierarchical( $taxonomy, $current, $term->term_id, $prefix . '– ' );
}
}
}
Функция:
- получает термины текущего уровня (
parent = 0для верхнего уровня); - выводит каждый термин с отступом для дочерних;
- рекурсивно вызывает саму себя для потомков.
Использование функции в фильтре
Теперь, когда функция готова, можно использовать её для построения <select> в форме фильтрации.
Пример:
<select name="property_location">
<option value="">Выберите локацию</option>
<?php
$this->get_terms_hierarchical(
'location',
isset($_POST['property_location']) ? intval($_POST['property_location']) : 0
);
?>
</select>
Таким образом, пользователь сможет выбрать и родительский, и дочерний термин.
Выбранное значение передаётся методом POST, после чего используется в WP_Query для фильтрации.
Добавление поддержки нескольких таксономий
Для расширения фильтра добавим второй <select> — например, по типу недвижимости (property_type).
Процесс аналогичен:
<select name="property_type">
<option value="">Тип недвижимости</option>
<?php
$this->get_terms_hierarchical(
'property_type',
isset($_POST['property_type']) ? intval($_POST['property_type']) : 0
);
?>
</select>
Теперь фильтр может одновременно учитывать обе таксономии: локацию и тип.
Фильтрация в WP_Query
После отправки формы добавим условия в запрос:
$args = [
'post_type' => 'property',
'tax_query' => []
];
if ( !empty($_POST['property_location']) ) {
$args['tax_query'][] = [
'taxonomy' => 'location',
'field' => 'term_id',
'terms' => intval($_POST['property_location']),
];
}
if ( !empty($_POST['property_type']) ) {
$args['tax_query'][] = [
'taxonomy' => 'property_type',
'field' => 'term_id',
'terms' => intval($_POST['property_type']),
];
}
$query = new WP_Query( $args );
Такой подход позволяет динамически собирать фильтр по нескольким параметрам, комбинируя их в tax_query.
Результат
После настройки:
- Фильтр отображает иерархию терминов с отступами.
- Пользователь может выбрать и родительский, и дочерний элемент.
- Система поддерживает фильтрацию сразу по нескольким таксономиям.
- Форма остаётся гибкой — достаточно скопировать код и заменить таксономию.
Практические советы
- Используйте
esc_attr()иesc_html()— для защиты от XSS при выводе данных. - Добавляйте визуальные разделители (например, символ “–”) — это повышает читаемость вложенных терминов.
- Используйте кэширование (например,
transient) для ускорения вывода при большом количестве терминов. - Не бойтесь рекурсии — она идеально подходит для обхода древовидных структур в WordPress.
Заключение
Иерархическая фильтрация по таксономиям делает интерфейс фильтра в WordPress гораздо более удобным и интуитивным.
Пользователь видит структуру данных и может точно выбрать нужную категорию, не запутываясь в длинных списках.
А реализовать такую функциональность можно буквально несколькими десятками строк кода.