В последнее время замечаю, что всё больше постов публикуются по просьбам читателей, так что пишите, возможно и для вас разберу какую-нибудь тему 🙂
Сейчас я покажу вам, как легко и просто создавать асинхронные фильтры записей/товаров (и те и вторые — это произвольные типы постов) на сайте при помощи всего лишь jQuery и WP_Query.
Для простоты не буду загружать пост ничем лишнем — рассмотрю только фильтрацию массива аргументов, постраничной навигации не будет, чтобы не усложнять пример. При необходимости могу дать подсказки по постраничной навигации в комментариях.
Форма будет состоять из выпадающего списка таксономий (для простоты — рубрик), диапазона значений произвольного поля (например пусть это будет цена), радио-кнопок сортировки по дате, по убыванию и возрастанию, а также чекбокса, который позволит отфильтровать посты, отобразив только те из них, у которых имеется миниатюра.
Неважно, элементы какой таксономии вы хотите вывести, в любых случаях функция 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>
Тут я подразумеваю, что вы уже знаете, что такое 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); } }); return false; }); });
Ну и последний шаг. Основная задача, с которой у многих людей возникают трудности — это задание аргументов для 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', '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'] ) && $_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 подробно раскрыта тут.
В данном случае куда вставлять код обработчика php?
Обычно же для подключения обработчика нужен скрипт, ктрй его вызывает, а сам обработчик в отдельном файле.
Обработчик отправляйте в
functions.php
, Дмитрий. Более подробно об этом.Добрый день Михаил, подскажите на примере как добавить свои произвольные поля в в вашу форму фильтрации:
Я так понимаю, что у вас проверяется минимальная и максимальная цена, мне этого не нужно , в теории мне нужен фильтр по категориям и трем произвольным полям которые у меня зарегистрированы и все.
Добрый день!
В принципе вам только немного нужно доработать код из этого поста - категории уже есть, цена - это и так уже произвольное поле.
Вот этот кусочек кода нужно задействовать для ваших трёх произвольных полей:
То есть я убрал из этого массива параметр сравнения и параметр числового значения. Дайте знать, если будут вопросы.
Привет Михаил!
У меня такой вопрос, вроде сделал по инструкции:
-добавил форму на страницу
-добавил script jquery
-добавил обработчик в functions.php
при нажатии на кнопку меня перебрасывает на страницу
testsite/wp-admin/admin-ajax.php
что не так? подскажите пожалуйста. Ведь ajax на то и ajax чтоб подгрузить данные на текущей странице, верно?
Привет,
верно,
такое происходит при наличии ошибок в JavaScript, прежде всего рекомендую открыть консоль браузера и посмотреть, что там интересного. Обычно там уже сразу написано, где именно находится проблема.
Консоль открыл, ошибок не показывает.
я еще приписал в скрипт строчку (в скрипт jquery):
console.log('TEST');
тест выводится и ошибок ни каких, при нажатии на кнопку переводит на страницу
testsite/wp-admin/admin-ajax.php
у меня тогда такой вопрос, а почему оно не должно переводить ? Ведь по сути у нас в форме указан наш admin-ajax.php.
А в самом скрипте jquery я не вижу чтоб поведение кнопки блокировалось, поэтому по логике вроде и должно перебросить. Или я не прав?
Очень хочу научиться делать фильтры).
И правда, не блокируется 🙂 ну так добавьте, неужели не рискнули попробовать? Я просто забыл туда дописать return false;
Добрый вечер, у меня такая же проблема, я так и не поняла как это исправить, где именно надо прописать return false;
Миша, добрый день. Как делать фильтры, я понял. Но как теперь мне вывести отфильтрованные товары стандартным loop'ом на страницу с помощью AJAX? Придётся писать свой шаблон для сетки товаров или есть стандартная функция вывода всех отфильтрованных товаров? По типу такого:
Т.е. функция по факту должна возвращать html код сетки товаров.
Нашёл решение:
Здравствуйте! Скажите, а как добавить постраничную навигацию - loadmore ajax к отфильтрованным постам? То есть отфильтровали по значению, а далее если их много подгружаем аяксом по кнопке "Показать еще"...
Здравствуйте Заур,
У меня определённо было подробный урок на эту тему, поищите пожалуйста 🙃 Если не ошибаюсь, он на английском языке.
Такое впечатление, что автор скопировал код со стороннего сайта, совершенно не понимая, как он работает.
В приведенном виде, код не будет работать никогда.
В jQuery скрипте не указан адрес по которому отсылается запрос, вместо него стоит не инициализированная переменная ajaxurl.
Передача функции обработчика вообще отсутствует.
В форме зачем-то задано скрытое поле, которое в остальном коде никак не используется...
Копипаст вещь, конечно, хорошая, но вы же делаете вид, что людей учите чему-то. А на самом деле сами не понимает, что пишите.
Ахаха, спасибо, посмеялся.
Зачем же так расстраиваться, Эдуард, если у вас ничего не получается 🙃 Да, урок не самый подробный, ну это уже мой выбор, могли бы просто задать вопрос, если вам что-то непонятно.
Например: "Добрый день, Миша! Я не могу понять, откуда берётся переменная ajaxurl, помогите пожалуйста." А вместо этого вы оставили после себя 💩 в комментариях.
Ну ОК, раз пошла такая пьянка, действительно, расскажите, откуда у вас берется переменная ajaxurl на фронт-энде.
Мы же здесь про фронт-энд говорим правда? Вряд ли вы здесь про поиск и фильтрацию в админке пишите. По крайней мере никаких замечаний по этому поводу у вас нет.
Заодно расскажите, зачем вы в ajax форме неиспользуемый вами атрибут action поставили, из-за чего собственно людей и перекидывает на адрес /wp-admin/admin-ajax.php, затрудняя отладку.
Скорее всего из
admin_url( 'admin-ajax.php' )
.Вероятно я предполагал в JS использовать
filter.attr('action')
, но забыл поменять.