Фильтры на AJAX

Урок 5

Зарегистрируйтесь или войдите и получите бесплатный доступ к первому уроку курса.

Урок 5

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

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

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

А теперь давайте приступим к нашему уроку. По шагам.

Шаг 1. HTML фильтра для сайта

Форма будет состоять из:

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

1.1 Добавляем список из рубрик/таксономий

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

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

if( $terms = get_terms( array( 'taxonomy' => '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 рубрики
	}
	echo '</select>';
endif;

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

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

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

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

1.3 Дата

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

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

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

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

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

1.5 HTML-форма фильтра целиком

echo '<form action="" method="POST" id="filter">';
 
// категории
if( $terms = get_terms( array( 'taxonomy' => '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 рубрики
	}
	echo '</select>';
}
 
// минимальная/максимальная цена
echo '<input type="text" name="cena_min" placeholder="Минимальная цена" />';
echo '<input type="text" name="cena_max" placeholder="Максимальная цена" />';
 
// дата по возрастанию/убыванию
echo '<label><input type="radio" name="date" value="ASC" /> Дата: по возрастанию</label>';
echo '<label><input type="radio" name="date" value="DESC" selected="selected" /> Дата: по убыванию</label>';
 
// чекбокс только с фото
echo '<label><input type="checkbox" name="featured_image" /> Только с миниатюрой</label>';
 
 
echo '<button>Применить фильтр</button><input type="hidden" name="action" value="myfilter">
</form>
<div id="response"><!-- тут фактически можете вывести посты без фильтрации --></div>';

Что делать с этим кодом?

Тут всё зависит от задачи, которая перед вами стоит. Например я могу создать какой-то шаблон страницы, в котором будут выводиться посты без фильтрации и присутствовать код фильтра, либо например сделать то же самое на странице блога, шаблон home.php или index.php (подробнее про шаблоны – тут). Ну или же можете посмотреть видео в конце урока.

Шаг 2. JavaScript (jQuery) скрипт для отправки запроса и получения данных

2.1 Подключение скриптов

Прежде, чем предлагать вам готовый jQuery-код, я бы хотел поговорить о том, как его подключить и куда вставить код в целом.

Во-первых, давайте в папке с темой создадим любой файл .js, пока пустой, например я могу создать filter.js.

Во-вторых, давайте подключим наш файл скрипта и сам jQuery функцией wp_enqueue_script() и wp_register_script(). Это можно сделать так:

add_action( 'wp_enqueue_scripts', 'truemisha_jquery_scripts' );
 
function truemisha_jquery_scripts() {
 
	wp_enqueue_script( 'jquery' );
 
	wp_register_script( 'filter', get_stylesheet_directory_uri() . '/filter.js', array( 'jquery' ), time(), true );
	wp_enqueue_script( 'filter' );
 
}

Можете закинуть в файл filter.js строчку jQuery( function( $ ) { alert( 'test' ); }, чтобы убедиться, что всё работает.

В-третьих, нам нужно получить URL обработчика AJAX в WordPress, это правильнеее всего делать через wp_localize_script(), в итоге в коде выше мы добавляем одну строчку:

wp_localize_script( 'filter', 'true_obj', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );

2.2 Сам код отправки запроса

Смело отправляем его в файл filter.js.

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

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

Этот код можете вставить в файл functions.php например или читайте этот гайд.

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

add_action( 'wp_ajax_myfilter', 'true_filter_function' ); 
add_action( 'wp_ajax_nopriv_myfilter', 'true_filter_function' );
 
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' ] ) && 'on' == $_POST[ 'featured_image' ]
	) {
		$args[ 'meta_query' ] = array( 'relation' => 'AND' );
 	}
 
	// условие 1: цена больше $_POST[ 'cena_min' ]
	if( isset( $_POST[ 'cena_min' ] ) ) {
		$args[ 'meta_query' ][] = array(
			'key' => 'cena',
			'value' => $_POST[ 'cena_min' ],
			'type' => 'numeric',
			'compare' => '>'
		);
	}
 
	// условие 2: цена меньше $_POST[ 'cena_max' ]
	if( isset( $_POST[ 'cena_max' ] ) ) {
		$args[ 'meta_query' ][] = array(
			'key' => 'cena',
			'value' => $_POST[ 'cena_max' ],
			'type' => 'numeric',
			'compare' => '<'
		);
	}
 
	// условие 3: миниатюра имеется
	if( isset( $_POST[ 'featured_image' ] ) && 'on' == $_POST[ 'featured_image' ] ) {
		$args[ 'meta_query' ][] = array(
			'key' => '_thumbnail_id',
			'compare' => 'EXISTS'
		);
	}
 
	query_posts( $args );
 
	if ( have_posts() ) {
      		while ( have_posts() ) : the_post();
			// тут вывод шаблона поста, например через get_template_part()
          		echo '<a href="' . get_permalink() . '">' . get_the_title() . '</a>';
		endwhile;
	} else {
		echo 'Ничего не найдено';
	}
 
	die();
}

Пара комментариев по коду:

  • Подробно про параметр tax_query (строки 13-19) можете почитать здесь.
  • Про meta_query у меня вообще есть отдельный урок.
Купить курс
  • 7 видеоуроков
  • Доступ к теме курса с готовым кодом после каждого урока
  • Единоразовый платёж
  • Доступ навсегда
  • Уроки актуальны в 2024-м году
4000 р

Нажав на кнопку, вы соглашаетесь c условиями предоставления услуг и с обработкой персональных данных.