/ Wordpress / Фильтр Ajax

Фильтр Ajax

HIT

10.10.2017

7153

2

Очередная попытка сделать фильтр wordpress, в этот раз применяя технологию ajax. По сути программирование фильтра — это изобретение велосипеда, но есть 2 момента: во-первых в процессе я начинаю лучше понимать процессы и механизмы wordpress, во-вторых я могу создать фильтр который мне необходим для конкретной задачи.

Итак, фильтр состоит из 3-х компонентов:

1. Сама форма фильтра и область вывода результатов.
2. Функция обработчик, которая по сути создает новый измененный запрос.
3. Скрипт js который доставляет без перезагрузки информацию на сервер и обратно.

Форма фильтра

Форма практически ничем не отличается от формы обычного фильтра. Стили можно также взять из того же фильтра.

<div id="filter"> 
<form class="filter" action="" method="">
  
<?php 

$getcat = get_the_category();
if($getcat[0]){
$cat_id=$getcat[0]->term_id;
}

//$cat_id = 35;

$args = array( 
'posts_per_page' => -1, 
'cat' => $cat_id,
//'post_type' => 'slide' 
);
$catposts = get_posts( $args );
?>	
	
	
  
<!-- Фильтр по произвольному полю -->	
	
<div><span class="name-group">Метаполя</span>
<span class="group-filter">  

<?php
foreach( $catposts as $post ){ 
  
setup_postdata($post);
							   						  
$all_meta_objects = get_post_meta($post->ID, 'country', true); // Для одиночных значений метаполей
$all_email_objects = get_post_meta($post->ID, 'power', true);							  
							  							  			  
if($all_meta_objects){ 
  $all_meta_ids[] = $all_meta_objects;
}
							  
if($all_email_objects){ 	
$all_meta2_ids[] = $all_email_objects;
}	
							  
}

wp_reset_postdata();
    
  
if ( $all_meta_ids ): ?>
  
<?php $meta_ids_unique = array_unique($all_meta_ids); ?> 
  
<label><select name="country" id="country">  
<option value=""></option>

<?php foreach($meta_ids_unique as $meta): ?>
  
<option value="<?php echo $meta; ?>"><?php echo $meta; ?> 
  
(<?php $args = array(
    //'post_type' => 'slide',
	'cat' => $cat_id,
    'meta_key' => 'country',
    'meta_value' => $meta,
    'posts_per_page' => -1); 

$posts = get_posts($args);
$number = 0;
foreach ($posts as $post) :
    $number++;
endforeach;

echo $number;
wp_reset_query(); ?>)</option>    

<?php endforeach; ?>
  
</select></label>  

<?php endif; ?>	
  
<?php if ( $all_meta2_ids ): ?>
  
<?php $meta2_ids_unique = array_unique($all_meta2_ids); ?>  
  
<label><select name="power" id="power"> 
<option value=""></option> 

<?php foreach($meta2_ids_unique as $meta2): ?>  
  
<option value="<?php echo $meta2; ?>"><?php echo $meta2; ?></option> 
  
<?php endforeach; ?>
  
</select></label>
  
<?php endif; ?>	
  
</span></div>

<div>
<span class="name-group">Даты записей</span>  
<span class="group-filter">   

<div class="box">с <input type="date" name="date-68" value="" class="textbox" id="date-after"></div>
<div class="box">по <input type="date" name="date-69" value="" class="textbox" id="date-before"></div>
  
</span>  
</div>



<!-- Фильтр по меткам -->
  
<div>
<span class="name-group">Метка</span> 
<span class="group-filter">	  
<?php

foreach( $catposts as $post ){ setup_postdata($post);
							   
	$all_tag_objects = get_the_tags();												  
							  
	if($all_tag_objects){
  
		foreach($all_tag_objects as $tag) {
		  
			if($tag->count > 0) { $all_tag_ids[] = $tag->term_id; }
		}
	}						   
}

wp_reset_postdata();




if ( $tag->count > 0 ): ?>
  
<?php $tag_ids_unique = array_unique($all_tag_ids); ?>  

<?php foreach($tag_ids_unique as $tag_id): ?>
  
  
<?php $post_tag = get_term( $tag_id, 'post_tag' ); ?>
  
<label>
<input class="metka" type="checkbox" name="tags" 
  value="<?php echo $post_tag->term_id; ?>">
  
 <span><?php echo $post_tag->name; ?> 
 <sup>

<?php 

$args = array(
	'category__in' => $cat_id, 
    'tag__in' => $post_tag->term_id,
    'posts_per_page' => -1
);
	


$posts = get_posts($args);
$number = 0;
foreach ($posts as $post) :
    $number++;
endforeach;

echo $number;
wp_reset_query(); ?> 
 
 </sup></span>
</label>  

<?php endforeach; ?>

<?php endif; ?>		  
</span>
</div>






<!-- Фильтр по терминам произвольной таксономии -->

<div><span class="name-group">Лэйбл</span> 
<span class="group-filter">	

<?php

foreach( $catposts as $post ){ setup_postdata($post);
							   						  
$all_term_objects = wp_get_post_terms($post->ID, 'label');							  
							  
							  
						   
if($all_term_objects){
	foreach($all_term_objects as $term) {
			if($term->count > 0) { $all_term_ids[] = $term->term_id;}
		}
	}						   
}

wp_reset_postdata();
    
  
if ( $term->count > 0 ): ?>
  
<?php $term_ids_unique = array_unique($all_term_ids); ?>  
  
<?php foreach($term_ids_unique as $term_id): ?>
  
  
<?php $post_term = get_term( $term_id, 'label' ); ?>


  
<label>
<input class="label" type="checkbox" name="labels" 
  value="<?php echo $post_term->term_id; ?>">

<span><?php echo $post_term->name; ?> 
<sup>
  
<?php $args = array(
	'tax_query' => array(
		array(
			'taxonomy' => 'label',
		    'field' => 'id',
			'terms' => $post_term
		),
	),  
	'cat' => $cat_id,
	'posts_per_page' => -1
);  

$posts = get_posts( $args );

$number = 0;
foreach ($posts as $post) :
    $number++;
endforeach;

echo $number;
wp_reset_query(); ?>   
  
</sup></span>
</label>  

<?php endforeach; ?>

<?php endif; ?>		  
</span>
</div>  




  
<button type="submit" class="taguniq" title="<?php echo $cat_id; ?>"><i class="fa fa-filter" aria-hidden="true"></i>Фильтровать</button>
  
<div id="all" ><i class="fa fa-refresh" aria-hidden="true"></i> Очистить</div>
    
</form>
</div>

Функция-обработчик

Многие строки функции закомментированы, т.к. функция находится на стадии разработки. Скрипт полностью переработан, теперь он работает по технологии смешивания двух различных запросов. т.к. условия meta_query и tax_query в один запрос поместить невозможно, также и tax_query и tag. А остальные параметры можно добавлять к финальному объединенному запросу.

function ajax_filter_posts_scripts() {

  wp_register_script( 'afp_script', plugins_url('/ajax-filter-posts.js', __FILE__), array('jquery'), null, false );
  wp_enqueue_script( 'afp_script' );

  wp_localize_script( 'afp_script', 'afp_vars', array(
        'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Create nonce which we later will use to verify AJAX request
        'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
      )
  );
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);


// Собственно фильтр изменяющий запрос

function ajax_filter_get_posts() { 
  
//echo 'Поле1: ' .$_POST['taxonomy'];
//echo 'Поле2: ' .$_POST['taxonomy2']; 
  
//echo 'Метки: ' .$_POST['tags'];
//echo 'Лэйбл: ' .$_POST['labels'];  

//echo 'От: ' .$_POST['date'];
//echo 'До: ' .$_POST['date2']; 

//echo 'Количество: ' .$_POST['number'];
//echo 'Сортировать: ' .$_POST['sort'];
//echo 'Страница: ' .$_POST['pagine'];

  
  
// first query
if ($_POST['taxonomy'] != '') { 
$country =  $_POST['taxonomy'];
} else {
$country = 0;  
}

if ($_POST['taxonomy2'] != '') { 
$power =  $_POST['taxonomy2'];
} else {
$power = 0;  
}

$first_ids = get_posts( array(
    'fields'         => 'ids',
    'posts_per_page' => -1,
	'meta_query' => array(
  			'relation' => 'OR',
  			array(
			'key' => 'country',
			'value' => $country
			),
			array(
			'key' => 'power',
			'value' => $power
			)
	)
    
));

// second query
$tags = explode(" ", $_POST['tags']);

if ($_POST['labels'] != '') { 
$labels = explode(" ", $_POST['labels']);
} else {
$labels = 0;  
}

$second_ids = get_posts( array(
    'fields'         => 'ids',
	'posts_per_page' => -1,
	'tax_query' => array(
			'relation' => 'OR', //AND - записи которые одновременно входят в указанные таксономии; OR - записи принадлежащие любой из указанных таксономий
			array(
			'taxonomy' => 'post_tag',
  			'field'    => 'id',
			'terms'    => $tags,
            'operator' => 'IN' //AND - в записи должны быть все выбранные термины, IN - в записи должен быть хотя бы один из выбранных терминов
			),
			array(
			'taxonomy' => 'label',
  			'field'    => 'id',
			'terms'    => $labels,
            'operator' => 'IN'
			)
	)
)); 
  

// merging ids
$post_ids = array_merge( $first_ids, $second_ids);
  
//print_r ($post_ids);  
  
$args = array( 
  'post_type' => 'post',
  'post_status' => 'publish',
  'cat' => $_POST['category'],
  'posts_per_page' => $_POST['number'],
  'paged' => $_POST['pagine'], 
  'post__in'  => $post_ids,
  
);
  
$args['date_query'][] = array(
			'after'     => $_POST['date'],
			'before'    => $_POST['date2'],
			'inclusive' => true,
);

// Варианты сортировки
if ($_POST['sort'] == 'newest')  { $args['orderby'] = 'date'; $args['order'] = 'DESC';}
if ($_POST['sort'] == 'lastest') { $args['orderby'] = 'date'; $args['order'] = 'ASC'; }
if ($_POST['sort'] == 'title')   { $args['orderby'] = 'title'; $args['order'] = 'ASC';}
if ($_POST['sort'] == 'correct') { $args['orderby'] = 'modified';}
if ($_POST['sort'] == 'power')   { $args['orderby'] = 'meta_value_num'; $args['meta_key'] = 'power';}
if ($_POST['sort'] == 'count')   { $args['orderby'] = 'meta_value_num'; $args['meta_key'] = 'post_views_count';}

  
$theme_post_query = new WP_Query( $args );



while( $theme_post_query->have_posts() ) : 
   
$theme_post_query->the_post();
  
include(TEMPLATEPATH."/solus.php");  
  
endwhile;
  
 
 
// количество записей в дополнительном запросе 
if ($theme_post_query->found_posts == 0) {
  echo 'Нет записей удовлетворяющих запросу';
} else {
  echo 'В дополнительном запросе ';
  plural_form(
    $theme_post_query->found_posts,
    array('запись','записи','записей')
  );
}
  

//пэйджинация
if (  $theme_post_query->max_num_pages > 1 ) {
  
echo '<label><select name="posts_per_page" id="pagine">';
echo '<option value="1">1</option>';
 
echo $theme_post_query->max_num_pages;
echo ' страниц<br>';  

$i = 2;
  
while( $i <= $theme_post_query->max_num_pages ) :  
  
  echo '<option value="'.$i.'">'.$i.'</option>';
  
$i++;
  
endwhile;
  echo '</select></label>';
}


  
  
  
exit;  
}


add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');

Дополнил сортировкой и пока примитивной пэйджинацией (возможно нужно взять стандартную функцию пэйджинации и перезагружать ее). Чтобы работала сортировка где-то на странице нужно вывести это:

<div id="posts-sorting">
  
<form method="get" id="sorting" action="">
<div><span class="group-filter">  
  
<label><select name="select" id="sort">
<option value="">Исходная сортировка</option>  
<option value="lastest">по дате (сначала старые)</option>
<option value="title">по заголовку</option>  
<option value="correct">по дате изменения</option>
<option value="power">по мощности</option>
<option value="count">по количеству просмотров</option> 
</select></label>
  
<label><select name="posts_per_page" id="number">
<option value="">по 20 записей</option>  
<option value="40">по 40 записей</option>
<option value="60">по 60 записей</option>  
<option value="-1">все</option>
</select></label> 
  
</span></div>	  
</form>
  
</div>

Параметры произвольных полей

В фильтре у нас может встречаться множество произвольных полей. Необходимо выбрать принцип их взаимодействия:

  • AND — выводить записи содержащие оба поля
  • OR — выводить записи содержащие одно из полей

Но есть такой момент, что если в фильтре мы не выберем значения, то переменная передаст пустое значение и параметр выдаст все записи, у которых этот metakey пустой. Чтобы этого избежать делаем такую проверку,для разных полей она может быть разной:

if ($_POST['taxonomy'] != '') { 
$country =  $_POST['taxonomy'];
} else {
$country =  0;  
}

Либо можно придумать какой либо универсальный символ, которые не будет встречаться ни в одном meta — $country = ‘_’;

JS скрипт

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

jQuery(document).ready(function($) {
	
		//$('.taguniq').click( function(event) { //По нажатию на кнопку
		$('.filter').on('change', function () {  //При изменении формы

		// Prevent defualt action - opening tag page
		if (event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}

		// Get tag slug from title attirbute

	    var category = $(this).attr('title'); //Чтобы брать из этой же категории
	    var sortValues = $("#country option:selected").val();
	    var sortValues2 = $("#power option:selected").val();
	    var sortValues3 = $("#date-after").val();
	    var sortValues4 = $("#date-before").val();
	    var sortValues4 = $("#date-before").val();

	  
	    var arrList = $('.metka:checkbox:checked').map(function(){
    		return $(this).attr('value');
		}).get();
		var tags = arrList.join(', '); // преобразовываем массив в строку с разделителем ' '
		
		//alert (tags);
		
		var arrList = $('.label:checkbox:checked').map(function(){
    		return $(this).attr('value');
		}).get();
		var labels = arrList.join(', ');
			

		$('.tagged-posts').fadeOut();

		data = {
			action: 'filter_posts',
			afp_nonce: afp_vars.afp_nonce,
		    category: category,
			taxonomy: sortValues,
		    taxonomy2: sortValues2,
		    date: sortValues3,
		    date2: sortValues4,
		    tags: tags,
		  	labels:labels,
		};
	  
	  
		$.ajax({
			type: 'post',
			dataType: 'html',
			url: afp_vars.afp_ajax_url,
			data: data,
			success: function( data, textStatus, XMLHttpRequest ) {
				$('.tagged-posts').html( data );
				$('.tagged-posts').fadeIn();
				console.log( textStatus );
				console.log( XMLHttpRequest );
			},
			error: function( MLHttpRequest, textStatus, errorThrown ) {
				console.log( MLHttpRequest );
				console.log( textStatus );
				console.log( errorThrown );
				$('.tagged-posts').html( 'No posts found' );
				$('.tagged-posts').fadeIn();
			}
		})

	});
  
  
  
  	$('#all').click( function(event) {
	  

		// Получаем данные из различных атрибутов
	    var selecetd_cat = $('#curcat').attr('title');
 

		$('.tagged-posts').fadeOut();

		data = {
			action: 'filter_posts',
			afp_nonce: afp_vars.afp_nonce,
		    category: selecetd_cat, //Не передаем лишних параметров
		};
	  

		$.ajax({
			type: 'post',
			dataType: 'html',
			url: afp_vars.afp_ajax_url,
			data: data,
			success: function( data, textStatus, XMLHttpRequest ) {
				$('.tagged-posts').html( data );
				$('.tagged-posts').fadeIn();
				console.log( textStatus );
				console.log( XMLHttpRequest );
			},
			error: function( MLHttpRequest, textStatus, errorThrown ) {
				console.log( MLHttpRequest );
				console.log( textStatus );
				console.log( errorThrown );
				$('.tagged-posts').html( 'No posts found' );
				$('.tagged-posts').fadeIn();
			}
		})
	  
	  
    });
  
});

Поделиться в соц. сетях:

  • Похожие записи
  • Комментарии
  • Вложения
Фильтр по меткам (изменение основного запроса)

Фильтр по меткам (изменение основного запроса)

Реализуем фильтрацию записей по меткам путем изменения основного запроса на лету (ajax). Находим все теги записей входящих в категорию Данный код можно вставить в боковую колонку в виде виджета. <?php Читать далее »

/ /
Автоматическое определение координат по адресу

Автоматическое определение координат по адресу

В данном решении используется сервис geocode-maps.yandex.ru. Функция определения координат по адресу my_url_encode, my_url_decode — вспомогательные функции по кодировке/декодировке символов для правильного url-запроса. Использование функции Ajax-функция определения координат Добавим функцию подключения Читать далее »

Подгрузка постов «налету» II: Кнопка

Подгрузка постов «налету» II: Кнопка

Данный вариант подгрузки постов «налету» является альтернативой подгрузке постов при скроллинге. Только в данном методе посты будут подгружаться по нажатию на кнопку. Также учтены некоторые особенности шаблона данного сайта высота Читать далее »

Добавить комментарий

2 комментария

  1. Илья

    Что-то у меня сайт ложится, когда пытаюсь добавить этот код в functions.php

    1. Alexandr

      Это сложный функционал. Тут однозначно не смогу сказать где может быть ошибка. Смотрите на какой строке ошибка php.

Фильтр Ajax
Оформление заказа
Рекомендации для васОформление заказаOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.