2

I'm trying to hide my Woocommerce products that are out of stock from search, while still showing other post types in the results. The post type for the products are product.

add_action( 'pre_get_posts', 'hide_out_of_stock_from_search' );

function hide_out_of_stock_from_search( $q ) {

    if ( ! $q->is_search() ) return;
    if ( is_post_type_archive( 'product' ) ) {

        $q->set( 'meta_query', array(array(
            'key'       => '_stock_status',
            'value'     => 'outofstock',
            'compare'   => 'NOT IN'
        )));

    }

    remove_action( 'pre_get_posts', 'hide_out_of_stock_from_search' );
}

Everything is working except is_post_type_archive( 'product' ), which doesn't return true. If I replace it with true, it hide everything from search query (even posts and pages) except products that are in stock.

How can I set meta_query only for a specific post type without affecting other post types in the search query?

1 Answer 1

2

Quick explanation

Search is search and not an archive.

If you'll take a look at is_post_type_archive docs, you'll see that it:

Checks if the query is for an archive page of a given post type(s).

So if you're using this condition in your pre_get_posts, then it won't affect search results at all.

On the other hand this meta_query:

$q->set( 'meta_query', array(array(
    'key'       => '_stock_status',
    'value'     => 'outofstock',
    'compare'   => 'NOT IN'
)));

tells that you want to get only posts that have this meta value set and different than outoofstock, so it will exclude all posts and pages (because they don't have such meta value at all).

Solution

add_action( 'pre_get_posts', 'hide_out_of_stock_from_search' );

function hide_out_of_stock_from_search( $q ) {

    if ( ! is_admin() && $q->is_main_query() && $q->is_search() ) {

        $q->set( 'meta_query', array(
            'relation' => 'OR',
            array(
                'key'       => '_stock_status',
                'value'     => 'outofstock',
                'compare'   => 'NOT IN'
            ),
            array(
                'key'       => '_stock_status',
                'compare'   => 'NOT EXISTS'
            )
        ));

    }
}
1
  • 1
    Your explanation makes sense, and solution works. Thanks!
    – janlindso
    Commented Jul 5, 2018 at 23:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.