Skip to content

Instantly share code, notes, and snippets.

@Bobz-zg
Last active February 26, 2022 00:41
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save Bobz-zg/42337d22028230fe17ff03bd58824930 to your computer and use it in GitHub Desktop.
Save Bobz-zg/42337d22028230fe17ff03bd58824930 to your computer and use it in GitHub Desktop.
Filter WordPress posts by multiple custom taxonomy terms with AJAX Raw
<?php
/**
* AJAC filter posts by taxonomy term
*/
function vb_filter_posts_mt() {
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'bobz' ) )
die('Permission denied');
/**
* Default response
*/
$response = [
'status' => 500,
'message' => 'Something is wrong, please try again later ...',
'content' => false,
'found' => 0
];
$all = false;
$terms = $_POST['params']['terms'];
$page = intval($_POST['params']['page']);
$qty = intval($_POST['params']['qty']);
$pager = isset($_POST['pager']) ? $_POST['pager'] : 'pager';
$tax_qry = [];
$msg = '';
/**
* Check if term exists
*/
if (!is_array($terms)) :
$response = [
'status' => 501,
'message' => 'Term doesn\'t exist',
'content' => 0
];
die(json_encode($response));
else :
foreach ($terms as $tax => $slugs) :
if (in_array('all-terms', $slugs)) {
$all = true;
}
$tax_qry[] = [
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $slugs,
];
endforeach;
endif;
/**
* Setup query
*/
$args = [
'paged' => $page,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $qty,
];
if ($tax_qry && !$all) :
$args['tax_query'] = $tax_qry;
endif;
$qry = new WP_Query($args);
ob_start();
if ($qry->have_posts()) :
while ($qry->have_posts()) : $qry->the_post(); ?>
<article class="loop-item">
<header>
<h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
</header>
<div class="entry-summary">
<?php the_excerpt(); ?>
</div>
</article>
<?php endwhile;
/**
* Pagination
*/
if ( $pager == 'pager' )
vb_mt_ajax_pager($qry,$page);
foreach ($tax_qry as $tax) :
$msg .= 'Displaying terms: ';
foreach ($tax['terms'] as $trm) :
$msg .= $trm . ', ';
endforeach;
$msg .= ' from taxonomy: ' . $tax['taxonomy'];
$msg .= '. Found: ' . $qry->found_posts . ' posts';
endforeach;
$response = [
'status' => 200,
'found' => $qry->found_posts,
'message' => $msg,
'method' => $pager,
'next' => $page + 1
];
else :
$response = [
'status' => 201,
'message' => 'No posts found',
'next' => 0
];
endif;
$response['content'] = ob_get_clean();
die(json_encode($response));
}
add_action('wp_ajax_do_filter_posts_mt', 'vb_filter_posts_mt');
add_action('wp_ajax_nopriv_do_filter_posts_mt', 'vb_filter_posts_mt');
/**
* Shortocde for displaying terms filter and results on page
*/
function vb_filter_posts_mt_sc($atts) {
$a = shortcode_atts( array(
'tax' => 'post_tag', // Taxonomy
'terms' => false, // Get specific taxonomy terms only
'active' => false, // Set active term by ID
'per_page' => 12, // How many posts per page,
'pager' => 'pager' // 'pager' to use numbered pagination || 'infscr' to use infinite scroll
), $atts );
$result = NULL;
$terms = get_terms($a['tax']);
if (count($terms)) :
ob_start(); ?>
<div id="container-async" data-paged="<?= $a['per_page']; ?>" class="sc-ajax-filter sc-ajax-filter-multi">
<ul class="nav-filter">
<li>
<a href="#" data-filter="<?= $terms[0]->taxonomy; ?>" data-term="all-terms" data-page="1">
Show All
</a>
</li>
<?php foreach ($terms as $term) : ?>
<li<?php if ($term->term_id == $a['active']) :?> class="active"<?php endif; ?>>
<a href="<?= get_term_link( $term, $term->taxonomy ); ?>" data-filter="<?= $term->taxonomy; ?>" data-term="<?= $term->slug; ?>" data-page="1">
<?= $term->name; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<div class="status"></div>
<div class="content"></div>
<?php if ( $a['pager'] == 'infscr' ) : ?>
<nav class="pagination infscr-pager">
<a href="#page-2" class="btn btn-primary">Load More</a>
</nav>
<?php endif; ?>
</div>
<?php $result = ob_get_clean();
endif;
return $result;
}
add_shortcode( 'ajax_filter_posts_mt', 'vb_filter_posts_mt_sc');
/**
* Pagination
*/
function vb_mt_ajax_pager( $query = null, $paged = 1 ) {
if (!$query)
return;
$paginate = paginate_links([
'base' => '%_%',
'type' => 'array',
'total' => $query->max_num_pages,
'format' => '#page=%#%',
'current' => max( 1, $paged ),
'prev_text' => 'Prev',
'next_text' => 'Next'
]);
if ($query->max_num_pages > 1) : ?>
<ul class="pagination">
<?php foreach ( $paginate as $page ) :?>
<li><?php echo $page; ?></li>
<?php endforeach; ?>
</ul>
<?php endif;
}
@tanmaypatel86
Copy link

If you can create below your post as "Load More" pagination then It is very thankful for all developer
https://www.bobz.co/filter-wordpress-posts-by-custom-taxonomy-term-with-ajax-and-pagination

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

There is a different post with few minor modifications:
https://www.bobz.co/filter-wordpress-posts-multiple-taxonomy-terms-ajax-pagination
https://www.bobz.co/blog/demo-filter-wordpress-posts-multiple-taxonomy-terms-ajax-infinite-scroll

  1. static href="page-2" is in shortcode only, this is the code that's generated when you open page for first time.
    Next page is always 2, if you just opend the page because you start at page 1, click opens page 2.
    That's why it's static, there is no need to be dynamic here.

If it says undefined, it means you did not select element.
Problem is in Javascript you are not updating page number https://gist.github.com/Bobz-zg/8bc7c5a99a1ab6ee969a16004c0403d5
Check Line 59, this is dynamically updating "page-{next-number}"

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

I have set all codes for "Load more" pagination and it's working. Awesome. I am very thankful to you for guiding me and posts your code as permium.

Just need help on minor one query. when I click on load more button again again and when I reach button like this "You reached the end". You can see status "Posts found: undefined" so How can display total posts number here. if you can help then it's good for me.
http://prntscr.com/rpxlwb

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

@tanmaypatel86 I'm very happy that you managed to come up with solution on your own.
Usually people are looking for copy/paste solutions but that doesn't make them developers, kudos to you, very good job :)

I'm not sure which code are you using, if it's this: https://gist.github.com/Bobz-zg/8bc7c5a99a1ab6ee969a16004c0403d5
L73 : $status.html(data.message); is adding content to that status div (maybe data.message does not exist)
L96 : $status.html(msg); is also adding content to same status div

Tbh, looks like there is something wrong in my code there, not sure is complete needed and why I have added that at the first place.
Be sure to inspect what data is returned back, just console log or look in network panel for admin-ajax.php under XHR tab

@tanmaypatel86
Copy link

Thank you for your message. I will try to fix it using console log.

I have used this below code for that,

msg = textStatus;
if (textStatus === 'success') {
    msg = data.responseJSON.found;
}
$status.text('Posts found: ' + msg);

@tanmaypatel86
Copy link

I have also fixed it the issue of "Posts found: undefined" (when I click on load more button again again and when I reach button like this "You reached the end"). Thank you so much for amazing coding.

@Bobz-zg
Copy link
Author

Bobz-zg commented Apr 7, 2020

@tanmaypatel86 glad to hear that, good work!

@tanmaypatel86
Copy link

Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment