How To Search Product Using Custom Category And Create Short Code For Anywhere To Put And Search Product

Here we learn about how to search product using custom category and create short code for anywhere to put and search product.

Custom code copied and paste into your child theme’s functions.php file.

1. Create Custom Taxonomy using custom code.

we need to create two Custom Taxonomy ‘productyear_taxonomy‘ and ‘makemodel_taxonomy‘.

<?php
// Register Custom Taxonomy
function productyear_taxonomy() {
  $labels = array(
    'name'                       => _x( 'Year', 'Taxonomy General Name', 'text_domain' ),
    'singular_name'              => _x( 'Year', 'Taxonomy Singular Name', 'text_domain' ),
    'menu_name'                  => __( 'Year', 'text_domain' ),
    'all_items'                  => __( 'All Year', 'text_domain' ),
    'parent_item'                => __( 'Parent Item', 'text_domain' ),
    'parent_item_colon'          => __( 'Parent Item:', 'text_domain' ),
    'new_item_name'              => __( 'New Year', 'text_domain' ),
    'add_new_item'               => __( 'Add New Year', 'text_domain' ),
    'edit_item'                  => __( 'Edit Year', 'text_domain' ),
    'update_item'                => __( 'Update Item', 'text_domain' ),
    'view_item'                  => __( 'View Item', 'text_domain' ),
    'separate_items_with_commas' => __( 'Separate items with commas', 'text_domain' ),
    'add_or_remove_items'        => __( 'Add or remove items', 'text_domain' ),
    'choose_from_most_used'      => __( 'Choose from the most used', 'text_domain' ),
    'popular_items'              => __( 'Popular Items', 'text_domain' ),
    'search_items'               => __( 'Search Items', 'text_domain' ),
    'not_found'                  => __( 'Not Found', 'text_domain' ),
    'no_terms'                   => __( 'No items', 'text_domain' ),
    'items_list'                 => __( 'Items list', 'text_domain' ),
    'items_list_navigation'      => __( 'Items list navigation', 'text_domain' ),
  );
  $args = array(
    'labels'                     => $labels,
    'hierarchical'               => true,
    'public'                     => true,
    'show_ui'                    => true,
    'show_admin_column'          => true,
    'show_in_nav_menus'          => true,
    'show_tagcloud'              => true,
  );
  register_taxonomy( 'productyear', array( 'product' ), $args );
}
add_action( 'init', 'productyear_taxonomy', 0 );	

// Register Custom Taxonomy
function makemodel_taxonomy() {
  $labels = array(
    'name'                       => _x( 'Make & Model', 'Taxonomy General Name', 'text_domain' ),
    'singular_name'              => _x( 'Make & Model', 'Taxonomy Singular Name', 'text_domain' ),
    'menu_name'                  => __( 'Make & Model', 'text_domain' ),
    'all_items'                  => __( 'All Items', 'text_domain' ),
    'parent_item'                => __( 'Parent Item', 'text_domain' ),
    'parent_item_colon'          => __( 'Parent Item:', 'text_domain' ),
    'new_item_name'              => __( 'New Item Name', 'text_domain' ),
    'add_new_item'               => __( 'Add New Item', 'text_domain' ),
    'edit_item'                  => __( 'Edit Item', 'text_domain' ),
    'update_item'                => __( 'Update Item', 'text_domain' ),
    'view_item'                  => __( 'View Item', 'text_domain' ),
    'separate_items_with_commas' => __( 'Separate items with commas', 'text_domain' ),
    'add_or_remove_items'        => __( 'Add or remove items', 'text_domain' ),
    'choose_from_most_used'      => __( 'Choose from the most used', 'text_domain' ),
    'popular_items'              => __( 'Popular Items', 'text_domain' ),
    'search_items'               => __( 'Search Items', 'text_domain' ),
    'not_found'                  => __( 'Not Found', 'text_domain' ),
    'no_terms'                   => __( 'No items', 'text_domain' ),
    'items_list'                 => __( 'Items list', 'text_domain' ),
    'items_list_navigation'      => __( 'Items list navigation', 'text_domain' ),
  );
  $args = array(
    'labels'                     => $labels,
    'hierarchical'               => true,
    'public'                     => true,
    'show_ui'                    => true,
    'show_admin_column'          => true,
    'show_in_nav_menus'          => true,
    'show_tagcloud'              => true,
  );
  register_taxonomy( 'makemodel', array( 'product' ), $args );
}
add_action( 'init', 'makemodel_taxonomy', 0 );
?>

2. Create Product Filter Short code.

<?php	
/* Product Filter Short code */
function carfilter_func( $atts ) {
  $terms_year = get_terms(
    array(
      'taxonomy' => 'productyear',
      'order'    => 'DESC',
    ) );
  ob_start();
?>
  <div class="product_filter">
    <div class="product_filter_wrap">
      <div class="brp_select">
        <select class="proyear">
          <option value=""><?php echo esc_attr( __( 'Select Year' ) ); ?></option>
            <?php foreach($terms_year as $year){ ?>
            <option value="<?php echo $year->term_id; ?>"><?php echo $year->name ?></option>
          <?php } ?>					
        </select>
        <span>1 |</span>
      </div>
      <div class="brp_select">
        <select class="promake">
          <option value=""><?php echo esc_attr( __( 'Select Make' ) ); ?></option>
        </select>
        <span>2 |</span>				
      </div>
      <div class="brp_select">
        <select class="promodel">
          <option value=""><?php echo esc_attr( __( 'Select Model' ) ) ?></option>
        </select>
        <span>3 |</span>
      </div>
      <button type="button" name="Search" id="btn_search"/><?php echo _e( 'Go', 'text_domain'); ?></button>
      <div class="loader_filter">
        <div class="loader"></div>
      </div>
    </div>
  </div>
<?php
  return ob_get_clean();
}
add_shortcode( 'carfilter', 'carfilter_func' );

/*Ajax Call For on change events*/
add_action('wp_ajax_model_ajax_request','model_ajax_request');
add_action('wp_ajax_nopriv_model_ajax_request', 'model_ajax_request');

function model_ajax_request(){
  $args = array(
    'post_type' => 'product',
    'post_status' => 'publish',
    'posts_per_page' => -1,
    'tax_query' => array(
        array(
          'taxonomy' => 'productyear',
          'field' => 'id',
          'terms' => $_POST['id']
        )
      )
  );
  
  $product_query = new WP_Query( $args );
  
  if( !$_POST['model_id']){
    $make_array = array();
    foreach ( $product_query->posts as $product ) {
      $terms = get_the_terms( $product->ID , 'makemodel' );
      foreach ( $terms as $make ) {
        if( $make->parent == 0 ){
          $make_array[$make->term_id] = $make->name;
        }
      }
    }
    echo json_encode($make_array);
  }else{
    $model_array = array();
    foreach ( $product_query->posts as $product ) {
      $terms = get_the_terms( $product->ID , 'makemodel' );
      foreach ( $terms as $make ) {
        if( $make->parent == $_POST['model_id'] ){
          $model_array[$make->term_id] = $make->name;
        }
      }
    }
    echo json_encode( $model_array );
  }
  wp_die();
}
?>	

get_terms – Get the terms in a given taxonomy.

ob_start() – The output is stored in an internal buffer.

ob_get_clean() – Get the current contents and removed current output buffer.

3. Enqueue CSS, style, js and LocalizedData in ‘child-theme/functions.php’.

<?php
function myblog_enqueue_styles() {	
  /*product search enqueue*/
  wp_enqueue_script( 'filter-scripts', get_stylesheet_directory_uri() . '/js/product_filter.js', array( 'jquery' ), null, true );
  $myDataArray = array(
    'ajax_url' 		=> admin_url( 'admin-ajax.php' ),
    'shop_page_url' => get_permalink( woocommerce_get_page_id( 'shop' ) ),
  );
  wp_localize_script( 'filter-scripts', "LocalizedData", $myDataArray );
  
  wp_enqueue_style( 'filter-style', get_stylesheet_directory_uri() .'/css/product_filter.css' );
}
add_action( 'wp_enqueue_scripts', 'myblog_enqueue_styles' );
?>

4. Add below CSS code on file ‘child-theme/css/product_filter.css’.

.product_filter {
  padding: 15px;  
}
.product_filter_wrap{
  position: relative;
}
.select_error{
  border : 1px solid #FF0000;
}
.product_filter .proyear{
  padding: 5px 30px;
  height: 60px;
}
.product_filter #btn_search{
  height: 60px;
}
.product_filter .promake,
.product_filter .promodel{	
  padding: 5px 30px;
  height: 60px;
}
.brp_select{
  position:relative;
  float: left;
  margin-right: 10px;
}
.brp_select span{
  position:absolute;
  top: 17px;
  left: 10px;
}
select::-ms-expand{
  display: none;
}
.brp_select select{
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  display: block;	
}
.loader_filter{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);   
  z-index: 1;
}
.loader_filter .loader{
  border: 8px solid #000;
  border-radius: 50%;
  border-top: 8px solid #fff;
  width: 40px;
  height: 40px;
  -webkit-animation: spin 2s linear infinite;
  animation: spin 2s linear infinite;  
}

5. Add below JS code on file ‘child-theme/js/product_filter.js‘.

jQuery(document).ready(function(){
  jQuery( '.loader_filter' ).hide();
  jQuery( '.proyear' ).on( 'click', function(){
    jQuery( this ).toggleClass( 'active' );
  });	
  jQuery( '.proyear' ).on( 'change', function(){
    jQuery.ajax({
      type: 'POST',
      url: woocommerce_params.ajax_url,
      beforeSend: function() {
        jQuery( '.loader_filter' ).show();
        jQuery( '.product_filter .product_filter_wrap' ).addClass( 'loader_wrapper' );
      },
      data: {
        'action': 'model_ajax_request',
        'id': this.value
      },
      success:function(data) {
        var map_data = jQuery.parseJSON(data);
        jQuery( '.promake' ).html( '<option value="">Select Make</option>' );
        jQuery( '.promodel' ).html( '<option value="">Select Model</option>' );
        jQuery.each( map_data, function( key, value ) {
          jQuery( '.promake' ).append(jQuery( '<option>', {
            value: key,
            text: value
          }));
        });
        jQuery( '.proyear' ).removeClass( 'active' );
        jQuery( '.loader_filter' ).hide();
        jQuery( '.product_filter_wrap' ).removeClass( 'loader_wrapper' );
      }
    });
  });
  jQuery( '.promake' ).on( 'change', function(){
    var year_id = jQuery( '.proyear' ).val();
    jQuery.ajax({
      type: 'POST',
      url: woocommerce_params.ajax_url,
      beforeSend: function() {
        jQuery( '.loader_filter' ).show();
        jQuery( '.product_filter .product_filter_wrap' ).addClass( 'loader_wrapper' );
      },
      data: {
        'action': 'model_ajax_request',
        'model_id': this.value,
        'id': year_id
      },
      success:function(data) {
        var map_data = jQuery.parseJSON(data);
        jQuery( '.promodel' ).html( '<option value="">Select Model</option>' );
        jQuery.each( map_data, function( key, value ) {
          jQuery( '.promodel' ).append(jQuery( '<option>', {
            value: key,
            text: value
          }));
        });
        jQuery( '.loader_filter' ).hide();
        jQuery( '.product_filter_wrap' ).removeClass( 'loader_wrapper' );
      }
    });
  });
  
  jQuery( '#btn_search' ).click(function(){
    year  = jQuery( '.proyear' ).val();
    make  = jQuery( '.promake' ).val();
    model = jQuery( '.promodel' ).val();		
    if( year == '' ){
      jQuery('.proyear').focus().addClass('select_error');
    }else if( make == '' ){
      jQuery( '.proyear' ).removeClass( 'select_error' );
      jQuery( '.promake' ).focus().addClass( 'select_error' );
    }else if( model == ''){
      jQuery( '.proyear' ).removeClass( 'select_error' );
      jQuery( '.promake' ).removeClass( 'select_error' );
      jQuery( '.promodel' ).focus().addClass( 'select_error' );
    }else{
      window.location.href=LocalizedData.shop_page_url + '?proyear=' + year + '&promake=' + make + '&promodel=' + model;
    }
  });	
});

6. Add below code in ‘child-theme/functions.php’ for product(shop) page to display search product by the selected value.

<?php
/* search category function */
function is_subcategory( $cat_id = null ) {
  if ( is_tax( 'product_cat') ) {
    if ( empty( $cat_id )){
      $cat_id = get_queried_object_id();
    }
    $cat = get_term( get_queried_object_id(), 'product_cat' );
    if ( empty( $cat->parent ) ){
      return false;
    }else{
      return true;
    }
  }
  return false;
}

/*overwrite wp query*/
function product_filter_queries( $query ){	
  if ( ( is_post_type_archive( 'product' ) || is_subcategory() || is_archive() ) && $query->is_main_query()){
    if( isset( $_GET['proyear']) || $_GET['promake'] || $_GET['promodel'] ){			
      if( empty( $_GET['promodel'] ) ){
        $term_id = $_GET['promake'];
      }else{
        $term_id = $_GET['promodel'];
      }
      $taxquery = array(
        'relation' => 'AND',
      );
      if ( isset( $_GET['proyear'] ) && $_GET['proyear'] != '' ) {
        $taxquery[] = array(
                'taxonomy' 	=> 'productyear',
                'field' 	=> 'id',
                'terms' 	=> $_GET['proyear']
              );
      }
      if ( $term_id != '' ) {
        $taxquery[] = array(
                'taxonomy' 			=> 'makemodel',
                'field' 			=> 'id',
                'parent'   			=> $_GET['promake'],
                'terms' 			=> $term_id,
                'include_children' 	=> false
              );
      }
      $query->set( 'tax_query', $taxquery );			
    }
  }
}
add_action( 'pre_get_posts', 'product_filter_queries' );
?>

pre_get_posts – It is already has some default properties set depending on the page request.

7. Add shortcode inside your pages to display search product filter.

ShortCode is displayed inside square brackets like this:

[carfilter]

If WordPress theme template file use do_shortcode() function like this:

<?php echo do_shortcode( '[carfilter]' ); ?>

OUTPUT:

Submit a Comment

Your email address will not be published.

Subscribe

Select Categories