При разработке сайтов на WordPress часто возникает задача вывести список записей (постов) с возможностью фильтрации по категориям, меткам или кастомным полям. В этой статье мы подробно рассмотрим, как самостоятельно создать динамический список постов с фильтрами без использования громоздких плагинов, а также рассмотрим полезные плагины, которые могут облегчить задачу.
Почему нужно создавать собственный фильтр постов в WordPress
Стандартные архивы WordPress позволяют выводить записи по категориям или меткам, но они не всегда удобны для пользователей, особенно если нужно комбинировать несколько фильтров или добавить кастомные поля. Использование плагинов-фильтров может быть избыточным и замедлять сайт, а собственная реализация даст полный контроль и оптимальную скорость.
Кроме того, создание собственного фильтра – это отличный способ понять работу WP_Query, AJAX и frontend-разработки в WordPress.
Основные этапы создания динамического списка с фильтрами
- Создание пользовательского шаблона для вывода списка постов.
- Добавление формы фильтрации с необходимыми полями.
- Обработка данных фильтра на сервере с помощью WP_Query.
- Использование AJAX для динамического обновления списка без перезагрузки страницы.
Создаем шаблон вывода списка постов
В вашем шаблоне (например, page-posts-filter.php) добавим базовый цикл WordPress для вывода постов:
<?php
$wdream_filter_args = [
'post_type' => 'post',
'posts_per_page' => 10,
];
$query = new WP_Query($wdream_filter_args);
if ($query->have_posts()) :
echo '<div id="wdream-posts-list">';
while ($query->have_posts()) : $query->the_post();
echo '<article><h2>' . get_the_title() . '</h2></article>';
endwhile;
echo '</div>';
wp_reset_postdata();
else:
echo '<p>Посты не найдены.</p>';
endif;
?>
Этот базовый код мы будем расширять фильтрами и AJAX.
Добавляем форму фильтра
Для примера сделаем фильтр по рубрикам и по периоду публикации:
<form id="wdream-filter-form">
<label>Категория:</label>
<select name="category">
<option value="">Все</option>
<?php
$categories = get_categories();
foreach ($categories as $cat) {
echo '<option value="' . $cat->term_id . '">' . $cat->name . '</option>';
}
?>
</select>
<label>Период публикации:</label>
<select name="date_range">
<option value="">Все время</option>
<option value="week">За неделю</option>
<option value="month">За месяц</option>
<option value="year">За год</option>
</select>
<button type="submit">Фильтровать</button>
</form>
Эта форма отправит GET-запрос с параметрами, которые мы примем и обработаем.
Обработка фильтров в PHP с WP_Query
Добавим функцию в functions.php или в плагин, которая формирует аргументы WP_Query в зависимости от выбранных фильтров:
function wpdream_get_filtered_posts_args() {
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
];
if (!empty($_GET['category'])) {
$args['cat'] = intval($_GET['category']);
}
if (!empty($_GET['date_range'])) {
$date_query = [];
switch ($_GET['date_range']) {
case 'week':
$date_query = [
'after' => '1 week ago',
];
break;
case 'month':
$date_query = [
'after' => '1 month ago',
];
break;
case 'year':
$date_query = [
'after' => '1 year ago',
];
break;
}
if ($date_query) {
$args['date_query'] = [$date_query];
}
}
return $args;
}
Теперь можно в шаблоне использовать wpdream_get_filtered_posts_args() для создания запроса с фильтрами.
Добавляем динамическое обновление списка через AJAX
Чтобы не перезагружать страницу при фильтрации, реализуем AJAX-запросы.
JavaScript для отправки формы и обновления списка
document.getElementById('wdream-filter-form').addEventListener('submit', function(e) {
e.preventDefault();
const form = e.target;
const data = new FormData(form);
const params = new URLSearchParams();
for (const pair of data.entries()) {
params.append(pair[0], pair[1]);
}
fetch(wpdream_ajax_object.ajax_url + '?' + params.toString(), {
method: 'GET',
headers: {'X-Requested-With': 'XMLHttpRequest'},
})
.then(response => response.text())
.then(html => {
document.getElementById('wdream-posts-list').innerHTML = html;
})
.catch(console.error);
});
Для этого добавим в functions.php локализацию скрипта:
function wpdream_enqueue_scripts() {
wp_enqueue_script('wdream-filter', get_template_directory_uri() . '/js/wpdream-filter.js', ['jquery'], '1.0', true);
wp_localize_script('wdream-filter', 'wpdream_ajax_object', [
'ajax_url' => admin_url('admin-ajax.php'),
]);
}
add_action('wp_enqueue_scripts', 'wpdream_enqueue_scripts');
Обработка AJAX-запроса на сервере
Добавим обработчик AJAX в functions.php:
function wpdream_ajax_filter_posts() {
$args = wpdream_get_filtered_posts_args();
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<article><h2>' . get_the_title() . '</h2></article>';
}
} else {
echo '<p>Посты не найдены.</p>';
}
wp_die();
}
add_action('wp_ajax_wpdream_filter_posts', 'wpdream_ajax_filter_posts');
add_action('wp_ajax_nopriv_wpdream_filter_posts', 'wpdream_ajax_filter_posts');
В JavaScript нужно скорректировать URL для вызова AJAX с параметром action=wpdream_filter_posts:
fetch(wpdream_ajax_object.ajax_url + '?action=wpdream_filter_posts&' + params.toString(), { method: 'GET', headers: {'X-Requested-With': 'XMLHttpRequest'} })
Полезные плагины для фильтрации WordPress
- Clearfy Pro — оптимизирует работу сайта и может помочь с кешированием фильтров.
- WPCommunity — если нужно добавить фильтры и сортировку в сообщество.
- ABC Pagination — расширенная пагинация для списков с фильтрами.
Советы по оптимизации и безопасности
1. Всегда валидируйте и фильтруйте входящие данные (intval, sanitize_text_field и т.п.), чтобы избежать уязвимостей.
2. Используйте Transients API для кеширования результатов запросов, особенно если данных много и они редко меняются.
3. Подумайте о пагинации, чтобы не загружать сразу слишком много записей.
4. Минимизируйте количество запросов к базе данных и оптимизируйте их с помощью индексов.
Итог
Создание удобного динамического списка записей с фильтрами — задача, которая требует понимания WP_Query, AJAX и frontend-разработки. Мы рассмотрели, как сделать это своими силами, а также привели примеры кода и полезные рекомендации. Такой подход позволит сделать сайт более интерактивным и удобным для пользователей.