Очередная попытка сделать фильтр 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();
}
})
});
});
[site-socialshare]

Что-то у меня сайт ложится, когда пытаюсь добавить этот код в functions.php
Это сложный функционал. Тут однозначно не смогу сказать где может быть ошибка. Смотрите на какой строке ошибка php.