В современных проектах на WordPress часто требуется выводить сложные таблицы с возможностью фильтрации по нескольким уровням, чтобы пользователи могли быстро находить нужные данные. В этой статье мы подробно разберем, как создать динамические таблицы с вложенными фильтрами на основе мета-полей и таксономий, используя собственный код и минимальное количество плагинов. Такой подход поможет избежать излишней нагрузки на сайт и даст гибкость в настройках.
Почему нужны динамические таблицы с вложенными фильтрами
Статичные таблицы, созданные вручную или через классические конструкторы, неудобны при работе с большим объемом информации. Пользователь хочет фильтровать данные по нескольким критериям, например, сначала выбрать категорию товара, затем подкатегорию, а после — фильтр по цене или рейтингу.
Вложенные фильтры — это каскадный выбор: выбор в первом фильтре влияет на доступные значения во втором и так далее. В WordPress это можно реализовать через AJAX-запросы, что делает интерфейс удобным и быстрым.
Подготовка данных: мета-поля и таксономии
Для примера создадим таблицу с кастомными постами типа product, у которых есть таксономии product_category и product_subcategory, а также мета-поле price. Вложенный фильтр будет работать так: сначала выбирается категория, затем подгружаются подкатегории только для выбранной категории, и после можно фильтровать по цене.
Добавим таксономии в functions.php или в отдельном плагине:
function hueman_register_product_taxonomies() {
register_taxonomy('product_category', 'product', [
'hierarchical' => true,
'label' => 'Категории продуктов',
'show_ui' => true,
'rewrite' => ['slug' => 'product_category'],
]);
register_taxonomy('product_subcategory', 'product', [
'hierarchical' => true,
'label' => 'Подкатегории продуктов',
'show_ui' => true,
'rewrite' => ['slug' => 'product_subcategory'],
]);
}
add_action('init', 'hueman_register_product_taxonomies');
Для мета-поля цены можно использовать Advanced Custom Fields (ACF) или создать поле вручную.
Реализация AJAX-фильтрации с вложенными фильтрами
Создаем форму фильтра
В шаблоне страницы выводим форму с двумя выпадающими списками и полем для цены:
<form id="hueman-filter-form">
<select id="hueman-product-category" name="product_category">
<option value="">Выберите категорию</option>
<?php
$categories = get_terms(['taxonomy' => 'product_category', 'hide_empty' => false]);
foreach ($categories as $cat) {
echo '<option value="' . esc_attr($cat->term_id) . '">' . esc_html($cat->name) . '</option>';
}
?>
</select>
<select id="hueman-product-subcategory" name="product_subcategory" disabled>
<option value="">Выберите подкатегорию</option>
</select>
<input type="number" name="max_price" id="hueman-max-price" placeholder="Максимальная цена" min="0" />
<button type="submit">Фильтровать</button>
</form>
<div id="hueman-table-container"></div>
Обратите внимание, что список подкатегорий изначально отключен.
Подгрузка подкатегорий через AJAX
Добавим скрипт, который при выборе категории отправляет AJAX-запрос и подгружает подкатегории:
jQuery(document).ready(function($) {
$('#hueman-product-category').on('change', function() {
var catId = $(this).val();
if (!catId) {
$('#hueman-product-subcategory').html('<option value="">Выберите подкатегорию</option>').attr('disabled', true);
return;
}
$.ajax({
url: hueman_ajax_object.ajax_url,
method: 'POST',
data: {
action: 'hueman_get_subcategories',
category_id: catId
},
success: function(response) {
var options = '<option value="">Выберите подкатегорию</option>';
if (response.success) {
$.each(response.data, function(index, subcat) {
options += '<option value="' + subcat.term_id + '">' + subcat.name + '</option>';
});
$('#hueman-product-subcategory').html(options).attr('disabled', false);
} else {
$('#hueman-product-subcategory').html(options).attr('disabled', true);
}
}
});
});
});
В functions.php добавим обработчик AJAX:
function hueman_ajax_get_subcategories() {
$category_id = intval($_POST['category_id'] ?? 0);
if (!$category_id) {
wp_send_json_error();
}
$subcategories = get_terms([
'taxonomy' => 'product_subcategory',
'hide_empty' => false,
'parent' => 0, // Можно изменить логику, если есть вложенность
'meta_query' => [[
'key' => 'parent_category', // Зависит от структуры, может понадобиться кастомный метаполе или связь
'value' => $category_id,
'compare' => '=',
]],
]);
if (empty($subcategories) || is_wp_error($subcategories)) {
wp_send_json_error();
}
$data = [];
foreach ($subcategories as $subcat) {
$data[] = ['term_id' => $subcat->term_id, 'name' => $subcat->name];
}
wp_send_json_success($data);
}
add_action('wp_ajax_hueman_get_subcategories', 'hueman_ajax_get_subcategories');
add_action('wp_ajax_nopriv_hueman_get_subcategories', 'hueman_ajax_get_subcategories');
Важно: В данном примере предполагается, что у подкатегорий есть связь с родительской категорией через метаполе parent_category. Если используется иерархическая таксономия, то можно просто установить parent в get_terms.
Вывод таблицы с применением фильтров
При отправке формы будем делать AJAX-запрос, который вернет отфильтрованные продукты для вывода в таблице.
JS для обработки формы
$('#hueman-filter-form').on('submit', function(e) {
e.preventDefault();
var data = {
action: 'hueman_filter_products',
product_category: $('#hueman-product-category').val(),
product_subcategory: $('#hueman-product-subcategory').val(),
max_price: $('#hueman-max-price').val()
};
$.post(hueman_ajax_object.ajax_url, data, function(response) {
if (response.success) {
$('#hueman-table-container').html(response.data.html);
} else {
$('#hueman-table-container').html('<p>Товары не найдены.</p>');
}
});
});
PHP: обработка фильтра и вывод таблицы
function hueman_ajax_filter_products() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => [],
'meta_query' => [],
];
if (!empty($_POST['product_category'])) {
$args['tax_query'][] = [
'taxonomy' => 'product_category',
'field' => 'term_id',
'terms' => intval($_POST['product_category']),
];
}
if (!empty($_POST['product_subcategory'])) {
$args['tax_query'][] = [
'taxonomy' => 'product_subcategory',
'field' => 'term_id',
'terms' => intval($_POST['product_subcategory']),
];
}
if (!empty($_POST['max_price']) && is_numeric($_POST['max_price'])) {
$args['meta_query'][] = [
'key' => 'price',
'value' => floatval($_POST['max_price']),
'compare' => '<=',
'type' => 'NUMERIC',
];
}
// Если есть несколько tax_query, нужно указать relation
if (count($args['tax_query']) > 1) {
$args['tax_query']['relation'] = 'AND';
}
$query = new WP_Query($args);
if (!$query->have_posts()) {
wp_send_json_error();
}
ob_start();
echo '<table><thead><tr><th>Название</th><th>Категория</th><th>Подкатегория</th><th>Цена</th></tr></thead><tbody>';
while ($query->have_posts()) {
$query->the_post();
$categories = get_the_terms(get_the_ID(), 'product_category');
$subcategories = get_the_terms(get_the_ID(), 'product_subcategory');
$price = get_post_meta(get_the_ID(), 'price', true);
echo '<tr>';
echo '<td>' . get_the_title() . '</td>';
echo '<td>' . ($categories ? esc_html($categories[0]->name) : '') . '</td>';
echo '<td>' . ($subcategories ? esc_html($subcategories[0]->name) : '') . '</td>';
echo '<td>' . esc_html($price) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
wp_reset_postdata();
$html = ob_get_clean();
wp_send_json_success(['html' => $html]);
}
add_action('wp_ajax_hueman_filter_products', 'hueman_ajax_filter_products');
add_action('wp_ajax_nopriv_hueman_filter_products', 'hueman_ajax_filter_products');
Оптимизация и расширение функционала
Для повышения производительности рекомендуется использовать кеширование результатов AJAX-запросов, например, с помощью Transients API. Также можно добавить пагинацию и сортировку по столбцам таблицы.
Для удобства администрирования можно интегрировать поля с помощью плагина Clearfy Pro, который позволяет управлять метаполями и таксономиями, а также оптимизировать AJAX-запросы.
Заключение
Создание динамических таблиц с вложенными фильтрами в WordPress — задача вполне решаемая своими силами с минимальным использованием плагинов. Такой подход обеспечивает максимальную гибкость, а также позволяет создавать удобные интерфейсы для пользователей и администраторов. Используйте AJAX для подгрузки фильтров и результатов без перезагрузки страницы, а для улучшения UX — добавляйте пагинацию, сортировку и кеширование.