/ Wordpress / Фильтр Ajax

Фильтр Ajax

HIT

10.10.2017

7111

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();
			}
		})
	  
	  
    });
  
});

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

  • Похожие записи
  • Комментарии
  • Вложения
Избранное

Избранное

Реализуем функционал Избранное. Нам надо сделать кнопку добавить в Избранное в шаблоне самой записи и в цикле вывода записей категории. И отдельная страница Избранное где выводятся избранные записи. Плагин Favorites Читать далее »

Ajax форма с вложением файла

Ajax форма с вложением файла

Долго искал и нашел (здесь www.thenerdyblog.com) отличное решение — форма с вложением файла на ajax. Форма Скрипт Файл-обработчик Если нужно чтобы вложение было обязательным, то в условии else прописываем ошибку: Читать далее »

/
Json Начало

Json Начало

JSON (JavaScript Object Notation) — это текстовый протокол обмена данными, чем-то похожий на более привычный XML, но данные записываются в нем более компактно. Изначально он был разработан для нужд JavaScript Читать далее »

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

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

  1. Илья

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

    1. Alexandr

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

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