Добавление на сайт AJAX фильтра записей (типов постов) по рубрикам (таксономиям), произвольным полям либо по дате. Сортировка по убыванию / возрастанию.

В последнее время замечаю, что всё больше постов публикуются по просьбам читателей, так что пишите, возможно и для вас разберу какую-нибудь тему :)

Сейчас я покажу вам, как легко и просто создавать асинхронные фильтры записей/товаров (и те и вторые — это произвольные типы постов) на сайте при помощи всего лишь jQuery и WP_Query.

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

1. HTML форма фильтра

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

Таксономии

Неважно, элементы какой таксономии вы хотите вывести, в любых случаях функция get_terms() мне кажется ну самым удобным вариантом.

Для того, чтобы вывести элемент выпадающего списка с её помощью, вы можете воспользоваться следующим кодом:

if( $terms = get_terms( 'category', 'orderby=name' ) ) : // как я уже говорил, для простоты возьму рубрики category, но get_terms() позволяет работать с любой таксономией
	echo '<select name="categoryfilter"><option>Выберите категорию...</option>';
	foreach ($terms as $term) :
		echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // в качестве value я взял ID рубрики
	endforeach;
	echo '</select>';
endif;

Произвольные поля

Для примера возьмём минимальную и максимальную цену.

Ну тут всё легко, можно просто использовать два HTML-инпута. Конечно, будет гораздо интереснее элемент range с возможностью передвигания ползунков минимального и максимального значения. Но это уже на ваше усмотрение, плагинов jQuery много, что-нибудь да выберете.

<input type="text" name="cena_min" placeholder="Минимальная цена" />
<input type="text" name="cena_max" placeholder="Максимальная цена" />

Дата

Как я уже писал выше — это будут две radio-кнопки.

<label><input type="radio" name="date" value="ASC" /> Дата: по возрастанию</label>
<label><input type="radio" name="date" value="DESC" selected="selected" /> Дата: по убыванию</label>

Чекбокс «Только с фото»

Ну тут вообще всё просто.

<label><input type="checkbox" name="featured_image" /> Только с миниатюрой</label>

Форма целиком

Так как данная статья относится к разделу для начинающих, то не поленюсь теперь подвести итог и скинуть весь код получившейся формы.

<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
<?php
if( $terms = get_terms( 'category', 'orderby=name' ) ) : // как я уже говорил, для простоты возьму рубрики category, но get_terms() позволяет работать с любой таксономией
	echo '<select name="categoryfilter"><option>Выберите категорию...</option>'
	foreach ($terms as $term) :
		echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // в качестве value я взял ID рубрики
	endforeach;
	echo '</select>';
endif;
?>
<input type="text" name="cena_min" placeholder="Минимальная цена" />
<input type="text" name="cena_max" placeholder="Максимальная цена" />
<label><input type="radio" name="date" value="ASC" /> Дата: по возрастанию</label>
<label><input type="radio" name="date" value="DESC" selected="selected" /> Дата: по убыванию</label>
<label><input type="checkbox" name="featured_image" /> Только с миниатюрой</label>
<button>Применить фильтр</button>
<input type="hidden" name="action" value="myfilter">
</form>
<div id="response"></div>

2. jQuery-скрипт для отправки запроса и получения данных

Тут я подразумеваю, что вы уже знаете, что такое jQuery и умеете его как минимум подключать на сайт.

jQuery(function($){
	$('#filter').submit(function(){
		var filter = $(this);
		$.ajax({
			url:ajaxurl, // обработчик
			data:filter.serialize(), // данные
			type:filter.attr('method'), // тип запроса
			beforeSend:function(xhr){
				filter.find('button').text('Загружаю...'); // изменяем текст кнопки
			},
			success:function(data){
				filter.find('button').text('Применить фильтр'); // возвращаеи текст кнопки
				$('#response').html(data);
			}
		});
	});
});

3. Обработчик PHP

Ну и последний шаг. Основная задача, с которой у многих людей возникают трудности — это задание аргументов для WP_Query с учётом всех параметров фильтра выше.

function true_filter_function(){
	$args = array(
		'orderby' => 'date', // сортировка по дате у нас будет в любом случае (но вы можете изменить/доработать это)
		'order'	=> $_POST['date'] // ASC или DESC
	);
 
	// для таксономий
	if( isset( $_POST['categoryfilter'] )
		$args['tax_query'] = array(
			array(
				'taxonomy' => 'category',
				'field' => 'id',
				'terms' => $_POST['categoryfilter']
			)
		);
 
	// создаём массив $args['meta_query'] если указана хотя бы одна цена или отмечен чекбокс
	if( isset( $_POST['cena_min'] ) || isset( $_POST['cena_max'] ) || ( isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' ) )
		$args['meta_query'] = array( 'relation'=>'AND' ); // AND значит все условия meta_query должны выполняться
 
	// условие 1: цена больше $_POST['cena_min']
	if( isset( $_POST['cena_min'] ) )
		$args['meta_query'][] = array(
			'key' => 'cena_min',
			'value' => $_POST['cena_min'],
			'type' => 'numeric',
			'compare' => '>'
		);
 
	// условие 2: цена меньше $_POST['cena_max']
	if( isset( $_POST['cena_max'] ) )
		$args['meta_query'][] = array(
			'key' => 'cena_max',
			'value' => $_POST['cena_max'],
			'type' => 'numeric',
			'compare' => '<'
		);
 
	// условие 3: миниатюра имеется
	if( isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' )
		$args['meta_query'][] = array(
			'key' => '_thumbnail_id',
			'compare' => 'EXISTS'
		);
 
	die();
}
 
 
add_action('wp_ajax_myfilter', 'true_filter_function'); 
add_action('wp_ajax_nopriv_myfilter', 'true_filter_function');

Если особый интерес у вас вызывают последние две строчки, то тема AJAX в WordPress подробно раскрыта тут.

Подпишитесь, чтобы раз в неделю получать свежие статьи с блога по email.

По теме

Оставить комментарий / вопрос

phpjsHTMLCSSSQLПросто код
  Для того, чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или авторизуйтесь на сайте.
Получайте новости блога по email или следите за мной в социальных сетях.
  • Владимир: и на третьей строке не хватает скобки ) закрывающей if :)

  • Миша: Добрый вечер! Рекомендую получить ID пользователя через функцию get_current_user_id().

  • Дмитрий: Миша, подскажите пожалуйста, я использую такой редирект, но он не срабатывает: add_action( 'template_redirect', funct...

  • Миша: Ну как не определена - это аргумент функции. Или я просто вас не до конца понимаю.

  • Артем: Ага, понял. Вот только почему $args? Она же нигде не определена, по логике должна быть переменная $true_field_params или...