skip to Main Content

In WooCommerce, I want to display Out Of Stock products in the product category, but in terms of user experience, it is better to move these products to the end of the list so as not to confuse the user.

I am using actually Show Out of stock products at the end in Woocommerce answer code.

I made some attempts in this field, but every attempt brought a problem
For example, in an attempt to sort based on inventory over the sorting that the user had chosen, such as sorting based on price, it had priority and did not have the desired result.
Or in another attempt, only if the user chose the default sort, everything was correct, but if the user chose to sort by price or popularity, the existing and non-existent products were mixed together.

4

Answers


  1. Chosen as BEST ANSWER

    I found the answer to my question, I'm sharing it here to help others who have this problem. You just need to set a condition based on any type of categories and change the query according to that condition

    add_filter('posts_clauses', 'order_by_stock_status', 2000, 2);
    function order_by_stock_status($posts_clauses, $query)
    {
        global $wpdb;
    
        if (!is_admin() && (is_woocommerce() || is_product_tag() || is_product_category())) {
            if ($posts_clauses['orderby'] == 'wp_posts.menu_order ASC, wp_posts.post_title ASC') {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) INNER JOIN $wpdb->postmeta pricetable ON ($wpdb->posts.ID = pricetable.post_id) ";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC,CAST(pricetable.meta_value  AS INTEGER) ASC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND pricetable.meta_key = '_price' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            } elseif ($posts_clauses['orderby'] == ' wc_product_meta_lookup.total_sales DESC, wc_product_meta_lookup.product_id DESC ' || $posts_clauses['orderby'] == 'wp_posts.post_date DESC, wp_posts.ID DESC') {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id)";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            } elseif (strpos($posts_clauses['orderby'], 'wc_product_meta_lookup.min_price ASC') !== false) {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) INNER JOIN $wpdb->postmeta pricetable ON ($wpdb->posts.ID = pricetable.post_id) ";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC,CAST(pricetable.meta_value  AS INTEGER) ASC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND pricetable.meta_key = '_price' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            } elseif (strpos($posts_clauses['orderby'], 'wc_product_meta_lookup.max_price DESC') !== false) {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) INNER JOIN $wpdb->postmeta pricetable ON ($wpdb->posts.ID = pricetable.post_id) ";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC,CAST(pricetable.meta_value  AS INTEGER) DESC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND pricetable.meta_key = '_price' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            }
        }
        return $posts_clauses;
    }
    // Move OtOfStock Products To End Of Archive Loop
    

  2. To move out-of-stock products to the end of the product archive loop in WooCommerce, you can use a custom code snippet. WooCommerce doesn’t natively provide this functionality, so you’ll need to add some custom sorting logic. Below are the steps to achieve this:

    Access Your Theme’s Functions.php File:

    You’ll need to add the custom sorting logic to your WordPress theme’s functions.php file. You can access this file through your WordPress dashboard by navigating to Appearance > Theme Editor and then selecting functions.php.
    Add Custom Sorting Logic:

    Add the following code snippet to your functions.php file. This code will create a custom sorting option that moves out-of-stock products to the end of the list when a user selects it.

    // Add custom sorting option to move out-of-stock products to the end
      add_filter('woocommerce_get_catalog_ordering_args', 
      'custom_catalog_ordering_args');
       function custom_catalog_ordering_args($args)
       {
       if (isset($_GET['orderby']) && $_GET['orderby'] == 'custom_order') {
        $args['meta_key'] = '_stock_status';
        $args['orderby'] = 'meta_value';
        $args['order'] = 'ASC';
       }
      return $args;
      }
    
      // Add the custom sorting option to the dropdown
      add_filter('woocommerce_default_catalog_orderby_options', 
     'custom_default_catalog_orderby');
     add_filter('woocommerce_catalog_orderby', 'custom_catalog_orderby');
    
     function custom_default_catalog_orderby($options)
     {
     $options['custom_order'] = 'Out of Stock Last';
     return $options;
     }
    
     function custom_catalog_orderby($sortby)
    {
    $sortby['custom_order'] = 'Out of Stock Last';
    return $sortby;
    

    }

    Save and Test:

    After adding the code snippet to your functions.php file, save the changes. Now, when you go to your product category pages, you should see a new sorting option called "Out of Stock Last" in the product sorting dropdown.

    When a user selects this sorting option, out-of-stock products will be moved to the end of the product list.

    Please note that custom code changes like this should be made carefully, and it’s a good practice to have a backup of your site and be familiar with WordPress theme editing. Additionally, if your theme receives updates, you may need to revisit and potentially update this custom code to ensure compatibility.

    Login or Signup to reply.
  3. You can prioritize products based on their stock status. you can use WooCommerce’s built-in filters to adjust the sorting behavior.

    Something like this

    function custom_orderby($orderby, $query) {
        global $wpdb;
    
        $stock_order = "( CASE WHEN {$wpdb->prefix}postmeta.meta_key = '_stock_status' AND {$wpdb->prefix}postmeta.meta_value = 'instock' THEN 1 WHEN {$wpdb->prefix}postmeta.meta_key = '_stock_status' AND {$wpdb->prefix}postmeta.meta_value = 'outofstock' THEN 2 ELSE 3 END ),";
    
        if ($query->is_post_type_archive('product') && $query->is_main_query()) {
            $orderby = $stock_order . $orderby;
        }
        return $orderby;
    }
    add_filter('posts_clauses', 'sort_products_by_stock_status', 10, 2);
    
    function sort_products_by_stock_status($args) {
        global $wpdb;
    
        $args['join'] .= " LEFT JOIN {$wpdb->prefix}postmeta AS stock_status_meta ON {$wpdb->prefix}posts.ID = stock_status_meta.post_id AND stock_status_meta.meta_key = '_stock_status'";
        $args['orderby'] = "stock_status_meta.meta_value ASC, " . $args['orderby'];
    
        return $args;
    }
    
    Login or Signup to reply.
  4. I found the perfect solution to my problem.

    add_filter('posts_clauses', 'order_by_stock_status', 2000, 2);
    function order_by_stock_status($posts_clauses, $query)
    {
        global $wpdb;
    
        if (!is_admin() && (is_woocommerce() || is_product_tag() || is_product_category())) {
            if ($posts_clauses['orderby'] == ' wc_product_meta_lookup.total_sales DESC, wc_product_meta_lookup.product_id DESC ' || $posts_clauses['orderby'] == 'wp_posts.post_date DESC, wp_posts.ID DESC') {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id)";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            } elseif (strpos($posts_clauses['orderby'], 'wc_product_meta_lookup.min_price ASC') !== false) {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) INNER JOIN $wpdb->postmeta pricetable ON ($wpdb->posts.ID = pricetable.post_id) ";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC,CAST(pricetable.meta_value  AS INTEGER) ASC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND pricetable.meta_key = '_price' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            } elseif (strpos($posts_clauses['orderby'], 'wc_product_meta_lookup.max_price DESC') !== false) {
                $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) INNER JOIN $wpdb->postmeta pricetable ON ($wpdb->posts.ID = pricetable.post_id) ";
                $posts_clauses['orderby'] = " istockstatus.meta_value ASC,CAST(pricetable.meta_value  AS INTEGER) DESC, " . $posts_clauses['orderby'];
                $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND pricetable.meta_key = '_price' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
            }
        }
        return $posts_clauses;
    }
    // Move OtOfStock Products To End Of Archive Loop
    

    I added the above code to the functions.php file and changed the default sorting from the customization section to sort by the most recent, and the problem of displaying outofstock products at the end of the list and ACF repeater fields was also resolved.

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