Support » Developing with WordPress » Add AJAX text search for custom post type

  • Resolved courtneyjouning

    (@courtneyjouning)



    Hi,

    I currently have category filtering correctly with my custom post type. The code I I have for this to work is

    
    function video_filter_function(){
    
        if (!check_ajax_referer( 'my_nonce' )){
        wp_die();
        }else{
            $args = array(
               'orderby' => 'date', // we will sort posts by date
               'order' => $_POST['date'], // ASC или DESC
               'tax_query' => array(
                 array(
                   'taxonomy' => 'category',
                   'field' => 'id',
                   'terms' => $_POST['categoryfilter']
                )),
              'post_type' => 'videos',
            );
     
        $query = new WP_Query( $args );
     
     
        if( $query->have_posts() ) :
            while( $query->have_posts() ): $query->the_post();
    
                ?>
                <div class="video-grid-item">
                    <h2> <?php the_field('video_title'); ?></h2>
                    <p> <?php the_field('video_description'); ?></p>
    
                    <iframe src="https://player.vimeo.com/video/<?php the_field('vimeo'); ?>" width="640" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                </div>
    
    <?php  
            endwhile;
            wp_reset_postdata();
        else :
            echo 'No posts found';
        endif;
     
        die();
     
        die();
        }
    
        
    }
     
     
    add_action('wp_ajax_myfilter', 'video_filter_function'); 
    add_action('wp_ajax_nopriv_myfilter', 'video_filter_function'); 

    So I added

    if( isset( $_POST['description'] ) )
            $args = array(
                'post_type' => 'videos',
                'meta_key'      => 'video_description',
                'meta_value' => $_POST['description']
            );

    Which I was hoping would compliment the original function so they can search by category dropdown or a search input for the description.

    But nothing is coming up for the search results now.

    The page I need help with: [log in to see the link]

Viewing 11 replies - 1 through 11 (of 11 total)
  • You say you got it working, and then posted the code showing no sanitization of $_POST, and you posted your website link. Are you asking to be hacked?

    The code you added is out of context, so it doesn’t make sense.

    Hi @joyously , I have figured it out. And you’re right, how do I remove post?

    Ask in Slack #forums.

    Moderator Jan Dembowski

    (@jdembowski)

    Brute Squad and Volunteer Moderator

    There is nothing in this post that warrants removal. The post will not be removed or edited.

    See this for an explanation.

    https://wordpress.org/support/guidelines/#deleting-editing-posts

    Hi Courtney.

    Would you can provide us the entire code for your query?
    I was not able to understand where you are placing the last $args array in the first code.

    Remember: the best place to publish a large amount of code is in a service such as Pastebin or Gist and link it here.

    Hi,

    Function:

    
    function video_filter_function(){
    
        if (!check_ajax_referer( 'my_nonce' )){
        wp_die();
        }else{
            $args = array(
               'orderby' => 'date', // we will sort posts by date
               'order' => $_POST['date'], // ASC или DESC
               'tax_query' => array(
                 array(
                   'taxonomy' => 'category',
                   'field' => 'id',
                   'terms' => $_POST['categoryfilter']
                )),
              'post_type' => 'videos',
            );
    
            <em>if( isset( $_POST['description'] ) )
            $args = array(
                'post_type' => 'videos',
                'meta_key'      => 'video_description',
                'meta_value' => $_POST['description']
            );</em>
     
        $query = new WP_Query( $args );
     
     
        if( $query->have_posts() ) :
            while( $query->have_posts() ): $query->the_post();
    
                ?>
                <div class="video-grid-item">
                    <h2> <?php the_field('video_title'); ?></h2>
                    <p> <?php the_field('video_description'); ?></p>
    
                    <iframe src="https://player.vimeo.com/video/<?php the_field('vimeo'); ?>" width="640" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                </div>
    
    <?php  
            endwhile;
            wp_reset_postdata();
        else :
            echo 'No posts found';
        endif;
     
        die();
     
        die();
        }
    
        
    }
     
     
    add_action('wp_ajax_myfilter', 'video_filter_function'); 
    add_action('wp_ajax_nopriv_myfilter', 'video_filter_function'); 

    template:

    <form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
    		<?php
    
    			if( $terms = get_terms( 'category', 'orderby=name' ) ) : // to make it simple I use default categories
    				echo '<select name="categoryfilter"><option>All categories...</option>';
    				foreach ( $terms as $term ) :
    					echo '<option id="video-option" name="video-option" value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as the value of an option
    					$vidoption = sanitize_text_field( $_POST['video-option'] );
    					update_post_meta( $post->ID, 'video-option', $vidoption );
    				endforeach;
    				echo '</select>';
    				echo "string";
    
    			endif;
    
    		?>
    		<?php wp_nonce_field( 'my_nonce' ); ?>
    		<!-- <input type="text" name="description"> -->
    		<button>SEARCH</button>
    		<input type="hidden" name="action" value="myfilter">
    	</form>
    <div id="response"></div>
    <script type="text/javascript">
    	jQuery(function($){
    		$('#filter').submit(function(){
    			var filter = $('#filter');
    			$.ajax({
    				url:filter.attr('action'),
    				data:filter.serialize(), // form data
    				type:filter.attr('method'), // POST
    				beforeSend:function(xhr){
    					filter.find('button').text('Searching...'); // changing the button label
    				},
    				success:function(data){
    					filter.find('button').text('SEARCH'); // changing the button label back
    					$('#response').html(data); // insert data
    				}
    			});
    			return false;
    		});
    	});
    </script>

    Appreciate your help 🙂

    Please, read about Data Sanitization/Escaping before put this code in production.

    About your code:
    – There are missing <em> tags in your second IF, remove it.
    – You are using no meta_compare so the query is searching for video_descriptions that match 100% ( default value is ‘=’ ).
    – The second IF is not complementing the first, as you posted in your question: the second $args is replacing the first.

    Maybe this can help you:

    
    function video_filter_function() {
        check_ajax_referer( 'my_nonce' );
    
        // Remember to check for $_POST values you are using
        // to handle your errors
    
        $date = sanitize_text_field( $_POST['date'] );
        $categoryfilter = sanitize_text_field( $_POST['categoryfilter'] );
    
        $args = array(
            'post_type' => 'videos',
            'orderby'   => 'date',
            'order'     => $date,
            'tax_query' => array(
                array(
                    'taxonomy'  => 'category',
                    'field'     => 'id',
                    'terms'     => $categoryfilter
                )
            ),
        );
    
        if ( ! empty( $_POST['description'] ) ) {
            $description = sanitize_text_field( $_POST['description'] );
    
            $args['meta_query'] = array(
                'key'       => 'video_description',
                'value'     => $description,
                'compare'   => 'LIKE',
            );
        }
        
        $query = new WP_Query( $args );
    
        ...
    
    courtneyjouning

    (@courtneyjouning)

    Hi @mariovalney,

    Thank you for your assistance!

    My question here is how does this work if the user uses just one of the fields. Currently I have the $categoryfilter dropdown and the $description input. The user will only use of these, at the moment if I type ‘wargsergse’ which doesn’t match any of the descriptions, but if ‘all categories’ is still selected then it will show all videos still, it should show nothing becasue nothing is LIKE ‘wargsergse’.

    Hope that makes sense.

    Cheers,

    Courtney

    function video_filter_function(){
    
        check_ajax_referer( 'my_nonce' );
    
        $categoryfilter = sanitize_text_field( $_POST['categoryfilter'] );
        $date = sanitize_text_field( $_POST['date'] );
    
        if (!check_ajax_referer( 'my_nonce' )){
        wp_die();
        }else{
            $args = array(
               'orderby' => 'date', // we will sort posts by date
               'order' => $date, // ASC или DESC
               'tax_query' => array(
                 array(
                   'taxonomy' => 'category',
                   'field' => 'id',
                   'terms' => $categoryfilter
                )),
              'post_type' => 'videos',
            );
    
            if( ! empty( $_POST['description'] ) ){
                $description = sanitize_text_field( $_POST['description'] );
    
                $args['meta_query'] = array(
                    'key'      => 'video_description',
                    'meta_value' => $description,
                    'compare' => 'LIKE',
                );
            }
            
     
        $query = new WP_Query( $args );
     
     
        if( $query->have_posts() ) :
            while( $query->have_posts() ): $query->the_post();
                ?>
                <div class="video-grid-item">
                    <h2> <?php the_field('video_title'); ?></h2>
                    <p> <?php the_field('video_description'); ?></p>
    
                    <iframe src="https://player.vimeo.com/video/<?php the_field('vimeo'); ?>" width="640" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
                </div>
    
    <?php  
            endwhile;
            wp_reset_postdata();
        else :
            echo 'No posts found';
        endif;
     
        die();
     
        die();
        }
    
        
    }
     
     
    add_action('wp_ajax_myfilter', 'video_filter_function'); 
    add_action('wp_ajax_nopriv_myfilter', 'video_filter_function'); 
    Mario Valney

    (@mariovalney)

    My question here is how does this work if the user uses just one of the fields.

    Tax and Meta are queried with AND. In your code, if user fill only description the query will try to find a empty $categoryfilter in tax_query and the “wargsergse” LIKE value to video_description meta.

    Besides that I made a mistake in my code. Meta_query should be a array of array. This code fixes that and gives a better solution to users filling only one field: https://pastebin.com/ctGpKUJB

    Mario Valney

    (@mariovalney)

    It’s great it worked and thanks for mark this as solved.

    P.S.: thanks for your offer: it’s nice to see people being grateful about our help, but here in Forums we are all volunteer. So I have to invite you to take a look at our Guidelines in the Do Not Offer to Pay for Help section.

    courtneyjouning

    (@courtneyjouning)

    No worries – thanks again for the help!

Viewing 11 replies - 1 through 11 (of 11 total)
  • You must be logged in to reply to this topic.