wp query – WordPress Ajax form filter | Search by title with ajax form, breaks the other filters

Question

I have implemented a form within my code that gives the user the possibility to filter the products according to his needs.

The form was created in ajax, to increase the user experience level of the user

Step:

  1. I implement this code on the page where I want the form to appear

     <form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
    
         <input autocomplete="off"
                type="search"
                class="form-control rounded"
                name="search"
                id="search"
                style="min-width: 225px" />
    
    
         <?php
         if( $terms = get_terms( array( 'taxonomy' => 'category', 'orderby' => 'name' ) ) ) :
    
             echo '<select name="categoryfilter"><option value="">Select category...</option>';
             foreach ( $terms as $term ) :
                 echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as the value of an option
             endforeach;
             echo '</select>';
         endif;
         ?>
         <input type="text" name="price_min" placeholder="Min price" />
         <input type="text" name="price_max" placeholder="Max price" />
         <label>
             <input type="radio" name="date" value="ASC" /> Date: + costosto
         </label>
         <label>
             <input type="radio" name="date" value="DESC" selected="selected" /> Date: - costoso
         </label>
         <label>
             <input type="checkbox" name="featured_image" /> Only posts with featured images
         </label>
         <button>Apply filter</button>
         <input type="hidden" name="action" value="myfilter">
     </form>
    
  1. I create a file: custom.js and insert this code

     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('Processing...'); // changing the button label
             },
             success:function(data){
                 filter.find('button').text('Apply filter'); // changing the button label back
                 $('#response').html(data); // insert data
             }
         });
         return false;
     });
    });
    
  2. I call my js file, in functions.php

     wp_enqueue_script( 'CUSTOM-JS', get_template_directory_uri() . '/Custom.js', array(), '1.0.0', true);
    
  3. I always implement this code in functions.php

         add_action('wp_ajax_myfilter', 'misha_filter_function'); // wp_ajax_{ACTION HERE}
     add_action('wp_ajax_nopriv_myfilter', 'misha_filter_function');
    
     function misha_filter_function(){
         $args = array(
    
             'posts_per_page' => -1,
             'post_type' => 'produtcs',
             'orderby' => 'date', // we will sort posts by date
             'order' => $_POST['date'], // ASC or DESC
    
             );
    
    
    
    
         // for taxonomies / categories
         if( isset( $_POST['categoryfilter'] ) )
             $args['tax_query'] = array(
                 array(
                     'taxonomy' => 'category',
                     'field' => 'id',
                     'terms' => $_POST['categoryfilter']
                 )
             );
    
    
    
         // create $args['meta_query'] array if one of the following fields is filled
         if( isset( $_POST['price_min'] ) && $_POST['price_min'] || isset( $_POST['price_max'] ) && $_POST['price_max'] || isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' )
             $args['meta_query'] = array( 'relation'=>'AND' ); // AND means that all conditions of meta_query should be true
    
         // if both minimum price and maximum price are specified we will use BETWEEN comparison
         if( isset( $_POST['price_min'] ) && $_POST['price_min'] && isset( $_POST['price_max'] ) && $_POST['price_max'] ) {
             $args['meta_query'][] = array(
                 'key' => 'metakey_AMC_price',
                 'value' => array( $_POST['price_min'], $_POST['price_max'] ),
                 'type' => 'numeric',
                 'compare' => 'between'
             );
         } else {
             // if only min price is set
             if( isset( $_POST['price_min'] ) && $_POST['price_min'] )
                 $args['meta_query'][] = array(
                     'key' => 'metakey_AMC_price',
                     'value' => $_POST['price_min'],
                     'type' => 'numeric',
                     'compare' => '>'
                 );
    
             // if only max price is set
             if( isset( $_POST['price_max'] ) && $_POST['price_max'] )
                 $args['meta_query'][] = array(
                     'key' => 'metakey_AMC_price',
                     'value' => $_POST['price_max'],
                     'type' => 'numeric',
                     'compare' => '<'
                 );
         }
    
    
         // if post thumbnail is set
         if( isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' )
             $args['meta_query'][] = array(
                 'key' => '_thumbnail_id',
                 'compare' => 'EXISTS'
             );
         // if you want to use multiple checkboxed, just duplicate the above 5 lines for each checkbox
    
    
    
    
    
         if( !empty( $_POST['search'] ))
             $args = [
                 's' => $_POST['search'],
             ];
    
    
    
         add_filter( 'posts_where', 'title_filter', 10, 2 );
         $query = new WP_Query( $args );
         remove_filter( 'posts_where', 'title_filter', 10, 2 );
    
    
         if( $query->have_posts() ) :
             while( $query->have_posts() ): $query->the_post();
                 echo '<h2>' . $query->post->post_title . '</h2>';
                 $price = get_post_meta( get_the_ID(), 'metakey_AMC_price', true );
                 echo $price ;
             endwhile;
             wp_reset_postdata();
         else :
             echo 'No posts found';
         endif;
    
         die();
     }
    
    
    
    
    
     function title_filter( $where, &$wp_query ){
         global $wpdb;
         if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
             $where .= ' AND ' . $wpdb->posts . '.post_title LIKE '%' . esc_sql( like_escape( $search_term ) ) . '%'';
         }
         return $where;
     }
    

if you want to try this code by copying and pasting without these parts, go ahead, replacing post_type either with your cpt or with post

code to be removed if you want in functions.php | step 4:

                    if( !empty( $_POST['search'] ))
                        $args = [
                            's' => $_POST['search'],
                        ];
                    add_filter( 'posts_where', 'title_filter', 10, 2 );

                    remove_filter( 'posts_where', 'title_filter', 10, 2 );

the code works perfectly and does its own.

The problem arises when I implement the search input field, (search bar), which by writing the parameters and giving enter finds the results by filtering in the title of the custom post type, but when I want to have title + any other filter together then it stops working.

I wrote if you want to remove that piece of code to show that all the code without that piece has filters used in combination as it should be.

I get the problem only when I want

  1. I search for product by name and I get it

  2. use another filter of those available

Plus: I think the problem is in writing this piece:

                    if( !empty( $_POST['search'] ))
                        $args = [
                            's' => $_POST['search'],
                        ];

how can i fix?

0
user15775524 3 days 2021-11-25T17:56:52-05:00 0 Answers 0 views 0

Leave an answer

Browse
Browse