skip to Main Content

I’m creating Web Shop that sells tech and that kind of products. Client wants filters to search descriptions of the products and to filter it by that. For example: Let’s say 10 out of 50 products have ‘i7’ in their descriptions. I created the code that searches every products description and filters it correctly. Firstly, I created so that i search the term i want to filter, later i was planning on adding usual filters so that user can just click on it. Nevertheless, when i search ‘i7’ it just prints IDs of the products that contain ‘i7’ in their description below the search button. I want it to show only that products in Shop section where all products show, so basically to show it like regular filters.

Here’s the code of the "filter" i created:

function product_filter_plugin_enqueue_scripts() {
    wp_enqueue_script('product-filter-plugin-script', plugins_url('/assets/js/product-filter-plugin.js', __FILE__), array('jquery'), '1.0.0', true);
    wp_enqueue_style('product-filter-plugin-style', plugins_url('/assets/css/product-filter-plugin.css', __FILE__), array(), '1.0.0');
}
add_action('wp_enqueue_scripts', 'product_filter_plugin_enqueue_scripts');

// Handle the filtering functionality
function product_filter_plugin_handle_filtering() {
    // Check if a search query is submitted
    if (isset($_GET['search_query'])) {
        $search_query = sanitize_text_field($_GET['search_query']);

        // Set up the query arguments
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => -1,
        );

        // Query the products
        $products_query = new WP_Query($args);

        // Array to store filtered product IDs
        $filtered_product_ids = array();

        // Loop through each product and filter based on the search query
        if ($products_query->have_posts()) {
            while ($products_query->have_posts()) {
                $products_query->the_post();
                $product_id = get_the_ID();
                $product_description = get_the_content();

                // Filter based on the search query
                if (strpos($product_description, $search_query) !== false) {
                    // Add the filtered product ID to the array
                    $filtered_product_ids[] = $product_id;
                }
            }
        }

        // Reset the post data
        wp_reset_postdata();

        // Save the filtered product IDs to a file
        $filtered_ids_file_path = plugin_dir_path(__FILE__) . 'filter_id.txt';
        file_put_contents($filtered_ids_file_path, implode(',', $filtered_product_ids));


        return $filtered_product_ids;
    }
}

// Create a shortcode for the filtering functionality
function product_filter_plugin_shortcode($atts) {
    ob_start();
    ?>
    <div class="product-filter-container">
        <form class="product-filter-form" action="<?php echo esc_url(home_url('/')); ?>" method="GET">
            <input type="hidden" name="post_type" value="product">
            <input type="text" name="search_query" style="margin-bottom: 10px;" placeholder="Pretraga artikala">
            <input type="submit" value="Pretraži">
        </form>
    </div>
    <?php

    // Check if the current page is the shop page
    if (is_shop()) {
        $global_filtered_product_ids = product_filter_plugin_handle_filtering();
        if (!empty($global_filtered_product_ids)) {
            echo '<div class="product-filter-results">';
            echo "ID: " . implode(', ', $global_filtered_product_ids);
            echo '</div>';
        }
    }

    return ob_get_clean();
}
add_shortcode('product_filter', 'product_filter_plugin_shortcode');
/* product-filter-plugin.js */

(function($) {
    $(document).ready(function() {
      // Submit the filter form on enter key press in the input field
      $('.product-filter-form input[type="text"]').keypress(function(e) {
        if (e.keyCode === 13) {
          e.preventDefault();
          $('.product-filter-form').submit();
        }
      });
    });
  })(jQuery);
  
/* product-filter-plugin.css */

.product-filter-container {
    margin-bottom: 20px;
  }
  
  .product-filter-form input[type="text"] {
    padding: 8px;
    font-size: 16px;
  }
  
  .product-filter-results {
    margin-top: 20px;
  }
  
  .product-filter-results .product-item {
    margin-bottom: 10px;
    margin-top: 10px;
    padding: 10px;
    border: 1px solid #ccc;
  }
  

Any help is good. Thanks in advance

I tried using ChatGPT but it’s not that advanced yet. I tried adding code to the functions.php of my theme but it’s not working.

It prints out this: prints below search button

But, I want it to be here:

prints where all other products usually be

2

Answers


  1. First, in your jQuery code, (function($){ })(jQuery); already includes the ready() event, so you don’t need $(document).ready(function() {.

    Now there is a much lighter and efficient way to filter directly products from their description. Try the following revisited code version:

    add_action('wp_enqueue_scripts', 'product_filter_plugin_enqueue_scripts');
    function product_filter_plugin_enqueue_scripts() {
        wp_enqueue_script('product-filter-plugin-script', plugins_url('/assets/js/product-filter-plugin.js', __FILE__), array('jquery'), '1.0.0', true);
        wp_enqueue_style('product-filter-plugin-style', plugins_url('/assets/css/product-filter-plugin.css', __FILE__), array(), '1.0.0');
    }
    
    // Create a shortcode for the filtering functionality
    add_shortcode('product_filter', 'product_filter_plugin_shortcode');
    function product_filter_plugin_shortcode($atts) {
        ob_start();
        ?>
        <div class="product-filter-container">
            <form class="product-filter-form" action="<?php echo esc_url( wc_get_page_permalink( 'shop' ) ); ?>" method="GET">
                <input type="hidden" name="post_type" value="product">
                <input type="text" name="search_query" style="margin-bottom: 10px;" placeholder="Search articles">
                <input type="submit" value="Search">
            </form>
        </div>
        <?php
        return ob_get_clean();
    }
    
    // Filter products from their description
    add_filter('posts_clauses', 'filter_from_product_description', 10, 2 );
    function filter_from_product_description( $clauses, $query ) {
    
        if( is_shop() && isset($_GET['search_query']) && ! empty($_GET['search_query']) && $query->is_post_type_archive('product') ) {
            global $wpdb;
    
            $string = esc_attr($_GET['search_query']);
    
            $clauses['where'] .= " AND {$wpdb->prefix}posts.post_content LIKE '%{$string}%' ";
        }
        return $clauses;
    }
    

    The jQuery code in product-filter-plugin.js file:

    (function($) {
        $('.product-filter-form input[type="text"]').keypress(function(e) {
            if (e.keyCode === 13) {
                e.preventDefault();
                $('.product-filter-form').submit();
            }
        });
    })(jQuery);
    

    The CSS stays unchanged.

    Tested and works.

    Login or Signup to reply.
  2. You’re close to the solution! The main thing to achieve this is to use WordPress’s pre_get_posts action hook to alter the main query based on your search_query.

    Step 1: Use the pre_get_posts action hook

        function product_filter_plugin_pre_get_posts($query) {
        // Check if it's the main query, a product query, and there's a search_query parameter
        if ($query->is_main_query() && isset($_GET['search_query']) && !empty($_GET['search_query']) && $query->get('post_type') === 'product') {
            $search_query = sanitize_text_field($_GET['search_query']);
            $filtered_product_ids = product_filter_plugin_handle_filtering();
            // Modify the main query to only get products with the filtered IDs
            $query->set('post__in', $filtered_product_ids);
        }
     }
    add_action('pre_get_posts', 'product_filter_plugin_pre_get_posts');
    

    Step 2: Update your shortcode
    Remove the part where you output the filtered product IDs, as the main WooCommerce loop will handle the display.

    function product_filter_plugin_shortcode($atts) {
        ob_start();
        ?>
        <div class="product-filter-container">
            <form class="product-filter-form" action="<?php echo esc_url(home_url('/shop/')); ?>" method="GET">
                <input type="hidden" name="post_type" value="product">
                <input type="text" name="search_query" style="margin-bottom: 10px;" placeholder="Pretraga artikala">
                <input type="submit" value="Pretraži">
            </form>
        </div>
        <?php
        return ob_get_clean();
    }
    

    Step 3: Ensure your theme supports filtering
    Ensure the WooCommerce templates in your theme use the main WordPress query. If the theme has a custom WP_Query for the shop page, it might bypass the filtering.

    Final thoughts: After these changes, searching for a term will redirect you to the shop page, showing only the products that match the criteria in their descriptions. Always test thoroughly, especially when altering the main query!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search