skip to Main Content

I have been able to show out of stocks products at the end with the default sorting using this snippet:

/**
 * @snippet       Order out of stock products at the end - WooCommerce
 * @author        Sebastian Velandia
 * @compatible    WooCommerce 3.8.0
 */
add_filter('posts_clauses', 'order_by_stock_status');
function order_by_stock_status($posts_clauses) {
    global $wpdb;
    // only change query on WooCommerce loops
    if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag() || is_product_taxonomy())) {
        $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'];
    }
    return $posts_clauses;
}

This works okey with the default sorting, but when you apply other sorting criteria like for example, by price, then it stops working and out of stock products become visible again from the beginning of the catalog.

How to fix this snippet to always display the out of stock products at the end despite the sorting applied in woocommerce catalog?

2

Answers


  1. So this seems to work in testing. The orderby clause when you change the WooCommerce sort order on the shop page is superseded by the ordering. So this uses the filter woocommerce_get_catalog_ordering_args to append to all sorting queries your orderby function before the choice from the dropdown.

    add_filter('woocommerce_get_catalog_ordering_args', 'dd_catalog_order');
    function dd_catalog_order(){
        add_filter('posts_clauses', 'keep_order_by_stock_status');
    }
    
    function keep_order_by_stock_status($posts_clauses){
        $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
        return $posts_clauses;    
    }
    
    Login or Signup to reply.
  2. this code worked for me (put in functions.php of your theme)

    /**
    * Sorting out of stock WooCommerce products - Order product collections by stock status, in-stock products first.
    */
    class iWC_Orderby_Stock_Status
    {
    public function __construct()
    {
    // Check if WooCommerce is active
    if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
    add_filter('posts_clauses', array($this, 'order_by_stock_status'), 2000);
    }
    }
    public function order_by_stock_status($posts_clauses)
    {
    global $wpdb;
    // only change query on WooCommerce loops
    if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag())) {
    $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'];
    }
    return $posts_clauses;
    }
    }
    new iWC_Orderby_Stock_Status;
    /**
    * END - Order product collections by stock status, instock products first.
    */
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search