• Hi I have managed to get an Ajax filter to work on my project archive page, however I read it is not secure unless I have use nonce on the ajax request.

    I got stuck, and would be grateful if someone could point me in the right direction to get the nonce to work. Here is my code:

    FILTER.PHP

    <?php
    
    function OB_filter_function(){
    
      // Check Security Nonce
        // if ( !wp_verify_nonce( $_POST['security'], 'ob-ajax-nonce') ) {
        //     wp_send_json_error( array('message' => 'Nonce is invalid.') );
        // }
      // check_ajax_referer( 'ob_ajax_object.security', 'security' );
      // echo 'success';
    
    			if(!empty($_POST['pjCat']))
    		  foreach($_POST['pjCat'] as $pjCat) {
    							$categories[] = $pjCat;
    		  }
    			$args['tax_query'] = array(
    				array(
    					'taxonomy' => 'project_category',
    					'field' => 'slug',
    					'terms' => $categories
    				)
    			);
    
    			$query = new WP_Query( $args );
    
    			if( $query->have_posts() ) : ?>
    
    			<div class="container-grid">
    
    				<?php
    				while( $query->have_posts() ): $query->the_post();?>
    					<div class="grid-item">
    							<a href="<?= the_permalink() ?>">
    								<?php
    								if ( has_post_thumbnail() ) {
    								    the_post_thumbnail();
    								}?>
    								<h3><?= the_title() ?></h3>
    							</a>
    					</div>
    					<?php
    				endwhile;?>
    				</div><!--end container-inner-->
    
    			<?php
    			wp_reset_postdata();
    			else :
    				echo 'No posts found';
    			endif;
    
    			wp_die();
    }
    
    /**
     * Check the referrer for the AJAX call.
     */
    function ob_callback() {
        check_ajax_referer( 'ob_ajax_object.security', 'security' );
        echo 'success';
        die;
    }
    
    ?>

    ARCHIVE-PROJECTS.PHP

    <div class="filterBox">
    
    					<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
                  <label class="container"><input id="checkAll" type="checkbox" name="checkAll" value="all" checked>All<span class="checkmark"></label>
    							<?php
    								if( $terms = get_terms( 'project_category', 'orderby=name' ) ) :
    									foreach ( $terms as $term ) :?>
    									<label class="container"><input type="checkbox" name="pjCat[]" value="<?= strtolower($term->name) ?>" checked/><?= $term->name ?><span class="checkmark"></label>
    									<?php endforeach;
    								endif;
    							?>
    
    							<button>Apply</button>
    
    							<input type="hidden" name="action" value="myfilter">
    			    </form>
    			</div>
    
    		<div id="response">
    
    				 <?php if ( have_posts() ) : ?>
    
    					<div class="container-grid">
    
    					<?php
    					/* Start the Loop */
    					while ( have_posts() ) :
    						the_post();?>
    
    						<div class="grid-item">
    								<a href="<?= the_permalink() ?>">
    									<?php
    									if ( has_post_thumbnail() ) {
    											the_post_thumbnail();
    									}?>
    									<h3><?= the_title() ?></h3>
    								</a>
    						</div>
    
    					<?php endwhile;?>
            </div><!--end container-grid-->
    				<?php endif;  ?>
    
    				</div>
    		</div><!--end response-->
    

    FILTER.JS

    (function($) {
    
    "use strict";
    
    		$(document).ready(function(){
    
    			$('.filterBox').hide()
    
    			$('.toggleFilter').click(function(){
    				$('.filterBox').toggle();
    			});
    
    			$("#checkAll").click(function(){
    			$('input:checkbox').not(this).prop('checked', this.checked);
    			});
    
    			//".checkbox" change
    			$('input:checkbox').change(function(){
    			    //uncheck "select all", if one of the listed checkbox item is unchecked
    			    if(false == $(this).prop("checked")){ //if this item is unchecked
    			        $("#checkAll").prop('checked', false); //change "select all" checked status to false
    			    }
    			    //check "select all" if all checkbox items are checked
    			    if ($('input:checkbox:checked').length == $('input:checkbox').length ){
    			        $("#checkAll").prop('checked', true);
    			    }
    			});
    
    			$('#filter').submit(function(){
    				var filter = $('#filter');
    				$.ajax({
    					url: ob_ajax_object.ajax_url,
    					data: filter.serialize(), // form data
    					type: filter.attr('method'), // POST
    					security: ob_ajax_object.security, // Add a nonce/unique number to protect against XSS attacks
    					beforeSend:function(xhr){
    						filter.find('button').text('Processing...'); // changing the button label
    					},
    					success:function(data){
    						filter.find('button').text('Apply filter'); // changing the button label back
    		        $('#response').empty(); // remove existing
    						$('#response').hide().html(data).fadeIn(); // insert data
    					}
    				});
    				return false;
    			});
    
    		});
    
    })(jQuery);

    FUNCTIONS.PHP

    
    //add scripts
    
    function add_scripts() {
    	if (is_post_type_archive('projects')) {
    			wp_enqueue_script( 'ob_ajax_filter', get_stylesheet_directory_uri() . '/js/filter.js', array( 'jquery' ),'', true );
    			wp_localize_script(
    			'ob_ajax_filter',
    			'ob_ajax_object',
    			[
    				'ajax_url'  => admin_url( 'admin-ajax.php' ),
    				'security'  => wp_create_nonce( 'ob-ajax-nonce' )
    			]
    		);
    	}
    
    }
    
    add_action( 'wp_enqueue_scripts', 'add_scripts' );
    
    //FILTER PROJECTS BY CATEGORY
    
    require_once( __DIR__ . '/filter.php');
    add_action('wp_ajax_myfilter', 'OB_filter_function');
    add_action('wp_ajax_nopriv_myfilter', 'OB_filter_function');
    add_action( 'OB_filter_function', 'ob_callback' );
    • This topic was modified 6 years, 7 months ago by Ol1wp.
Viewing 3 replies - 1 through 3 (of 3 total)
  • As you are creating the nonce passing 'ob-ajax-nonce' as argument, i.e., calling wp_create_nonce( 'ob-ajax-nonce' ), you should check it using check_ajax_referer( 'ob-ajax-nonce', 'security' );. Give it a try and please come back here to tell if it worked.

    Also, code here in forums tend do be difficult to read (it scrolls vertical and horizontally), so next time please consider pasting it in pastebin.com and just leaving a link here ??

    Thread Starter Ol1wp

    (@ol1wp)

    Thanks for your reply.

    I tried that but still not working.

    https://pastebin.com/A37AaNnx
    https://pastebin.com/8rMueAi2
    https://pastebin.com/WRuhdMBT
    https://pastebin.com/A37AaNnx

    Also, what is the correct way to check that I the nonce is working?

    Hi @ol1wp,

    What are you trying to do? Also, the second parameter of add_action should be funtions names, not another action. So, this:

    add_action('wp_ajax_myfilter', 'OB_filter_function');
    add_action('wp_ajax_nopriv_myfilter', 'OB_filter_function');

    must be change to this:

    add_action('wp_ajax_myfilter', 'ob_callback');
    add_action('wp_ajax_nopriv_myfilter', 'ob_callback');

    and there is no need of this line:

    add_action( 'OB_filter_function', 'ob_callback' );

    Changing that will trigger your ob_callback function when user sends the ajax request here. Does that help you someway?

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘Ajax filter’ is closed to new replies.