Search code examples
phpwordpresswoocommerceproductshortcode

WP_Query issue when trying to get out of stock products in WooCommerce


I'm using shortcode to display all sold out WooCommerce items on a WordPress page. It works fine, except for throwing an error:

Warning: array_filter() expects parameter 1 to be array, null given in C:\xampp\htdocs\wordpress_4\wp-content\plugins\woocommerce\includes\class-wc-query.php on line 688

I figure that this means array_filter() expects an array, but is given null from the following code in my functions.php:

add_shortcode( 'out_of_stock_products', 'show_out_of_stock_products_shortcode' );
  
function show_out_of_stock_products_shortcode() {

    $args = array(
        'post_type' => 'product',
        'posts_per_page' => -1,
        'post_status' => 'publish',
        'meta_query' => array(
            array(
                'key' => '_stock_status',
                'value' => 'outofstock',
            )
        ),
        'fields' => 'ids',
    );
    
    $product_ids = get_posts( $args ); 
    $product_ids = implode( ",", $product_ids );
    
    return do_shortcode("[products ids='$product_ids']");
}

Shortcode: [out_of_stock_products]

Here's the WooCommerce function that expects the array but is given null:

public function get_meta_query( $meta_query = array(), $main_query = false ) {
    if ( ! is_array( $meta_query ) ) {
        $meta_query = array();
    }
    return array_filter( apply_filters( 'woocommerce_product_query_meta_query', $meta_query, $this ) ); //line 688
}

I'm not sure how to fix this. Maybe there is a better way to display sold out products altogether, though I like this version.

Could anyone help me fix this?

Source: https://www.businessbloomer.com/woocommerce-display-stock-products-shortcode/

Edit:

As @LoicTheAztec suggests, another bit of code than the ones posted above is responsible:

add_filter( 'woocommerce_product_query_meta_query', 'show_only_instock_products', 10, 2 );

show_only_instock_products( $meta_query, $query ) {
    if (  is_woocommerce() ) {
        $meta_query[] = array(
            'key'     => '_stock_status',
            'value'   => 'outofstock',
            'compare' => '!='
        );
        return $meta_query;
    }
}

I am using this to hide sold products from WooCommerce.


Solution

  • Update 2

    To get out of stock products, you can also use instead:

    1. A WC_Query using wc_get_products() function as follows:
    add_shortcode( 'out_of_stock_products', 'show_out_of_stock_products_shortcode' );
    function show_out_of_stock_products_shortcode() {
    
        $product_ids = (array) wc_get_products( array(
            'status'       => 'publish',
            'limit'        => -1,
            'stock_status' => 'outofstock',
            'return'       => 'ids',
        ) );
    
        $product_ids = empty($product_ids) ? '' : implode( ',', $product_ids );
    
        return empty($product_ids) ? '' : do_shortcode("[products ids='$product_ids']");
    }
    

    2). A WP_Query with a tax query like:

    add_shortcode( 'out_of_stock_products', 'show_out_of_stock_products_shortcode' );
    function show_out_of_stock_products_shortcode() {
    
        $product_ids = (array) get_posts( array(
            'post_type'      => 'product',
            'posts_per_page' => -1,
            'post_status'    => 'publish',
            'fields'         => 'ids',
            'tax_query' => array( array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => array('outofstock'),
            ) ),
        ) );
    
        $product_ids = empty($product_ids) ? '' : implode( ',', $product_ids );
    
        return empty($product_ids) ? '' : do_shortcode("[products ids='$product_ids']");
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.

    Related: Hide "out of stock" products with custom meta data In Woocommerce


    Addition: The problem comes from your edit (last code).

    Also since WooCommerce 3, you should use instead the following:

    add_filter( 'woocommerce_product_query_tax_query', 'show_only_instock_products', 10, 2 );
    show_only_instock_products( $tax_query, $query ) {
        if ( ! is_admin() ) {
            $tax_query[] = array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => array('outofstock'),
                'operator' => 'NOT IN'
            );
        }
        return $tax_query;
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.