В этом посте рассматривается кейс создания ajax фильтров и пагинации для постов. Без плагинов. Изучив данный кейс, вы сможете написать такую же пагинацию для любого типа постов и таксономий. Имеем такую страницу:
Это архив кастомного типа поста «projects» и 2 прикрепленные к нему таксономии: «projects_country» и «projects_services», а так же кнопка подгрузки следующей страницы. Пока компилируется код в вашем редакторе, здесь можно купить сессии телеграм. Для начала в шаблоне страницы выведем таксономии и посты. Код файла potfolio-page.php :
<?php /** * Template Name: Portfolio */ get_header();?> <div class="white-block white-projects"> <div class="wrapper filter-line"> <div class="select-block"> <i></i> <select name="country" class="country" id="country-select"> <option selected>Country</option> <?php $countries = get_terms('projects_country'); foreach ($countries as $country) { echo '<option value="'.$country->slug.'" data-country-id="'. $country->term_id.'">'.$country->name.'</option>'; } ?> </select> </div> <ul class="filter"> <li><a href="#">All</a></li> <?php $tax = 'projects_services'; $args = array( 'taxonomy' => $tax, 'hide_empty' => false, ); $terms = get_terms( $args ); foreach ($terms as $term): ?> <li><a href="#" data-service-id="<?php echo $term->term_id?>"><?php echo $term->name;?></a></li> <?php endforeach;?>
</ul>
</div>
</div>
<?php
$args = array(
‘post_type’ => ‘projects’,
);
$projects = new WP_Query($args);
$max_pages = $projects->max_num_pages; // узнаем общее количество страниц постов
if($projects->have_posts()) : ?>
<div class=»projects» id=»ajax-portfolio-container»>
<div class=»project-block» >
<?php while($projects->have_posts()): $projects->the_post();?>
<a href=»<?php the_permalink();?>»>
<?php the_post_thumbnail(‘project-thumb’)?>
<p class=»title-events big-text»><?php the_title();?></p>
</a>
<?php endwhile;?>
</div>
<?php
if($max_pages > 1){ ?> // если страниц больше одной, то выводим кнопку с data-атрибутом следующей страницы
<a id=»load-more-events» href=»#» class=»btn btn-orange» data-page=»2″>Load More</a>
<?php }?>
</div>
<?php wp_reset_postdata();
endif;?>
<?php get_footer();?>
</code></pre>
<p> </p>
<p>Данный код выводит select со странами, список с типами услуг, сами посты, а так же кнопку «Загрузить еще», если есть вторая страница с постами. Обратите внимание на data-атрибуты в тегах с таксономиями и кнопке подгрузки. Именно из них мы и будем получать нужные данные для фильтрации и пагинации. Для того, что бы работать с ajax запросами в WordPress через фронт-энд нам нужно: создать функцию обработчик в <strong>functions.php </strong>нашей темы; написать jQuery код для отправки запроса на обработчик. Для начала выведем в глобальнуюю Javascript переменную адрес «/wp-admin/admin-ajax.php». На этот адрес мы будем отправлять наши запросы. В <strong>functions.php </strong>добавляем такой код:</p>
<p> </p>
<pre><code class=»php»>
<?php
function js_variables(){
$variables = array (
‘ajax_url’ => admin_url(‘admin-ajax.php’),
);
echo ‘<script type=»text/javascript»>window.wp_data = ‘ . json_encode($variables) . ‘;</script>’;
}
add_action(‘wp_head’,’js_variables’);
?>
Данный код выводит select со странами, список с типами услуг, сами посты, а так же кнопку «Загрузить еще», если есть вторая страница с постами. Обратите внимание на data-атрибуты в тегах с таксономиями и кнопке подгрузки. Именно из них мы и будем получать нужные данные для фильтрации и пагинации. Для того, что бы работать с ajax запросами в WordPress через фронт-энд нам нужно: создать функцию обработчик в functions.php нашей темы; написать jQuery код для отправки запроса на обработчик. Для начала выведем в глобальнуюю Javascript переменную адрес «/wp-admin/admin-ajax.php». На этот адрес мы будем отправлять наши запросы. В functions.php добавляем такой код:
<?php function js_variables(){ $variables = array ( 'ajax_url' => admin_url('admin-ajax.php'), ); echo '<script type="text/javascript">window.wp_data = ' . json_encode($variables) . ';</script>'; } add_action('wp_head','js_variables'); ?>
Далее напишем jQuery код для обработки клика по селекту, списку с категориями и кнопке «Загрузить еще», который будет собирать данные из data-атрибутов и отправлять POST на адрес «/wp-admin/admin-ajax.php» и экшн, который мы создадим позже. Фильтровать мы будем по двум таксономиям одновременно и отношением «И». Т.е. «страна» И «тип услуги». Обработаем смену select’а со странами:
<script> jQuery('#country-select').on('change', function(){ var service = jQuery('.white-projects .filter a.active').data('service-id'); //собираем данные из data-атрибутов var country = jQuery(this).find('option:selected').data('country-id'); $.ajax({ type: "POST", url: window.wp_data.ajax_url, //адрес из глобальной переменной data : { action : 'get_projects', //название нашего обработчика, который создадим поже service_id : service, //id услуги из списка услуг country_id : country //id страны }, success: function (data) { jQuery('#ajax-portfolio-container').html(data); // заменяем содержимое контейнера ответом с сервера $('#ajax-portfolio-container .project-block a').css('opacity', 1); } }); }); </script>
В данном коде action — название функции обработчика, которую мы создадим позже, service_id и country_id -это id терминов, по которым нужно выбрать посты. «jQuery(‘#ajax-portfolio-container’).html(data);» — заменит содержимое нашего контейнера ответом с сервера.
Далее обработаем клик по типу услуг:
<script> jQuery('.white-projects .filter a').on('click', function(e){ e.preventDefault(); jQuery('.white-projects .filter a').removeClass('active'); jQuery(this).addClass('active'); var service = jQuery(this).data('service-id'); var country = jQuery("#country-select").find('option:selected').data('country-id'); $.ajax({ type: "POST", url: window.wp_data.ajax_url, data : { action : 'get_projects', service_id : service, country_id : country }, success: function (data) { jQuery('#ajax-portfolio-container').html(data); $('#ajax-portfolio-container .project-block a').css('opacity', 1); } }); }); </script>
И, наконец, клик по кнопке «Загрузить еще»:
<script> jQuery('body').on('click','#load-more-events', function(e){ e.preventDefault(); var service = jQuery(this).data('service-id'); // если посты уже отфильтрованы, то в кнопку для загрузки следующей страницы var country = jQuery(this).data('country-id'); // мы будем записывать id таксономий. var page = jQuery(this).data('page'); // номер страницы для загрузки var button = jQuery(this); $.ajax({ type: "POST", url: window.wp_data.ajax_url, data : { action : 'get_projects', service_id : service, country_id : country, paged : page }, success: function (data) { button.remove(); //удаляем кнопку jQuery('#ajax-portfolio-container').append(data); // добавляем в контейнер ответ с сервера } }); }); </script>
Отправку запросов мы настроили, теперь нужно создать обработчик. Для этого нам нужно будет использовать два хука: wp_ajax_(action) и wp_ajax_nopriv_(action). Второй нужен для того, чтобы к нему могли обращаться неавторизованные пользователи. Итоговый код должен быть примерно таким :
<?php function my_action_callback() { echo 'Hello!'; wp_die(); }
add_action(‘wp_ajax_(action)’, ‘my_action_callback’);
add_action(‘wp_ajax_nopriv_(action)’, ‘my_action_callback’);
?>
Обратите внимание, что функция должна обязательно возвращать данные через return или echo. Так же в конце функции обязательно ставим wp_die(); . В нашем случае мы пишем такой код в functions.php :
<?php function get_projects() { global $post; $service_id = $_POST['service_id'] ? $_POST['service_id'] : ''; //получаем POST данные $country_id = $_POST['country_id'] ? $_POST['country_id'] : ''; //Если в POST пусто - оставляем переменные пустыми $paged = $_POST['paged'] ? $_POST['paged'] : 1; // Если в paged пусто, то будем считать, что нужна первая страница $return_html = ''; // Весь HTML код мы записываем в переменную $args = array( // составляем запрос 'post_type' => 'projects', 'paged' => $paged, ); if (!empty($country_id) && !empty($service_id)) { // если переменные с ID таксономий не пусты, то добавляем tax_query с отношением "И" $args['relation'] = 'AND'; } if (!empty($service_id)) { $args['tax_query'][] = array( 'taxonomy' => 'projects_serices', 'terms' => $service_id ); } if (!empty($country_id)) { $args['tax_query'][] = array( 'taxonomy' => 'projects_country', 'terms' => $country_id ); } $projects = new WP_Query($args); $max_pages = $projects->max_num_pages; // получаем общее число страниц с выбранными постами if ($projects->have_posts()): $return_html .= '<div class="project-block">'; // собираем такую же разметку как в начальном шаблоне while ($projects->have_posts()): $projects->the_post(); $thumbnail = get_the_post_thumbnail($post->ID, 'project-thumb'); $title = get_the_title(); $permalink = get_the_permalink(); $return_html .= '<a href="' . $permalink . '">'; $return_html .= $thumbnail; $return_html .= '<p class="title-events big-text">' . $title . '</p>'; $return_html .= '</a>'; endwhile; $return_html .= '</div>'; endif; if ($paged < $max_pages) { // если текущая страница меньше общего числа страниц, то выводим кнопку для подгрузки $next_page = $paged + 1; // в дата атрибуты кнопки передаем номер следующей страницы и id текущих терминов $return_html .= '<a id="load-more-events" href="#" class="btn btn-orange" data-page="'. $next_page .'" data-service-id="'. $service_id .'" data-country-id="'.$country_id.'">Load More</a>'; } wp_reset_postdata(); echo $return_html; // возвращаем html код wp_die(); // обязательно "умираем" }
add_action(‘wp_ajax_get_projects’, ‘get_projects’); // наши хуки
add_action(‘wp_ajax_nopriv_get_projects’, ‘get_projects’);
?>
Результат работы кода:
Как добавить кнопку сброса всех фильтров до первоначального состояния чтоб повторно отфильтровать?
Нужно послать ajax на get_projects без параметров сервиса, страны и страницы. И вам прилетит просто первая страница сервисов. Ну и сбросить фильтры в первоначальное положение с помощью jQuery.
Более подробно можно почитать здесь: https://wp-kama.ru/id_2018/ajax-v-wordpress.html