Фильтры на AJAX
Урок 5
Сейчас я покажу вам, как легко и просто создавать асинхронные фильтры записей/товаров (и те и вторые — это произвольные типы постов) на сайте при помощи всего лишь jQuery и WP_Query.
Для простоты не буду загружать пост ничем лишнем — рассмотрю только фильтрацию массива аргументов, постраничной навигации не будет, чтобы не усложнять пример.
А теперь давайте приступим к нашему уроку. По шагам.
Форма будет состоять из:
Неважно, элементы какой таксономии вы хотите вывести, в любых случаях функция 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;
Для примера возьмём минимальную и максимальную цену.
Ну тут всё легко, можно просто использовать два HTML-инпута. Конечно, будет гораздо интереснее элемент range с возможностью передвигания ползунков минимального и максимального значения. Но это уже на ваше усмотрение, плагинов jQuery много, что-нибудь да выберете.
echo '<input type="text" name="cena_min" placeholder="Минимальная цена" />'; echo '<input type="text" name="cena_max" placeholder="Максимальная цена" />';
Как я уже писал выше — это будут две radio-кнопки.
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 '<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
(подробнее про шаблоны – тут). Ну или же можете посмотреть видео в конце урока.
Прежде, чем предлагать вам готовый 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' ) ) );
Смело отправляем его в файл 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; }); });
Этот код можете вставить в файл 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
у меня вообще есть отдельный урок.