exclude specific product from product list

Hello all,

We have a situation where products get discontinued. It's easy to conditionally remove product_meta via mp_product.php, but it more difficult to remove the product from product list i.e. mp_category.php.

I have found that https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts is the way to go, but I can't seem to get it quite right to target 'product'. Here's my code thus far:

add_action('pre_get_posts', 'exclude_products_productlist');

function exclude_products_productlist( $query ) {
        if( ! is_admin() && $query->is_main_query() && is_post_type_archive('product') ) {
                $query->set('post__not_in', array(5316));
    }
}

Any pointers would be most welcome!

Best, Andy

  • Vinod Dalvi

    Hi Andy,

    I hope you are well today and thank you for your question.

    You can achieve this by using the following code.

    add_action('pre_get_posts', 'exclude_products_productlist');
    
    function exclude_products_productlist( $query ) {
    	global $mp;
     	$request_path = $_SERVER['REQUEST_URI'];
        $path = explode("/", $request_path); // splitting the path
        $last = end($path);
        $last = prev($path);
            if( ! is_admin() && trim($mp->get_setting( 'slugs->products' ) ) == $last ) {
                    $query->set('post__not_in', array(5316));
        }
    }

    Best Regards,
    Vinod Dalvi

  • shelms1

    Hi Vinod, and thanks for your swift reply!

    I tried your solution and it seems not to work.
    For testing, I echo a text so I can see if a page is affected by the function.

    I continued working with a solution in this post I found on the subject:
    http://wordpress.stackexchange.com/questions/167032/exclude-particular-posts-in-archive-php ...and came up with a working solution, however I'm not sure it's entirely "correct" or efficient code, as it seems to target product archives exclusively, yet I have nothing calling product specifically in the code. The echoed text only appears on product archive pages.

    It is somewhat frustrating that I cannot target pages with is_post_type_archive('product')
    Since the code below "works" the MarketPress query must not be the main_query.

    Here is my current code:

    add_action( 'pre_get_posts', 'exclude_products_productlist', 1 );
    
    function exclude_products_productlist( $query ) {
        if ( !is_home() || is_admin() || $query->is_main_query() )
            return;
    
        if ( $query->is_archive() ) {
            $query->set( 'post__not_in', array( 5316 ) );
            echo '<h1>this is a product archive</h1>';
        }
    }

    Thanks once again for your time and energy!
    Best, Andy

  • shelms1

    Hi Vinod,

    I have a correction to the above code! !is_home() takes the echoed text off the homepage, but it the function does not affect the query.

    This code below works, but the echoed text is visible on all archives placed on homepage.

    function exclude_products_productlist( $query ) {
        if ( is_admin() || $query->is_main_query() )
            return;
    
        if ( $query->is_archive() ) {
            $query->set( 'post__not_in', array( 5316 ) );
            echo '<h1>this is a product archive</h1>';
        }
    }
  • Ash

    Hello @shelms1

    I hope you are well today.

    You can remove that line (I know you used for testing):
    echo '<h1>this is a product archive</h1>';

    It is true that, the following code affect all archive pages:
    $query->is_archive()
    But the post ID 5316 is unique. There is no post or page or anything that have that ID. So, the code runs in all archive pages, but doesn't affect the original query result at all except the product page.

    Though you can try this:

    function exclude_products_productlist( $query ) {
        if ( is_admin() || $query->is_main_query() )
            return;
    
        if ( $query->post_type == 'product' && $query->is_archive() ) {
            $query->set( 'post__not_in', array( 5316 ) );
            echo '<h1>this is a product archive</h1>';
        }
    }

    Hope it helps :slight_smile: Please feel free to ask more question if you have any.

    Cheers
    Ash

  • shelms1

    Hello @Ashok,

    Thanks again for your swift reply. The added $query->post_type == 'product' looks like it should work, but, just like is_post_type_archive(), it does not. Also I have found that the whole section:

    if ( is_admin() || $query->is_main_query() )
            return;

    ...is not needed to achieve my current results. I can use only:

    add_action( 'pre_get_posts', 'exclude_products_productlist', 1 );
    function exclude_products_productlist( $query ) {
            if ( $query->is_archive() ) {
                    $query->set( 'post__not_in', array( 5316 ) );
                    echo '<h1>this is a product archive</h1>';
                    }
            }

    Product no.5316 is not on archives, and I still see it in the admin screen, which is the desired result. So something is still not quite right, because that could should exclude from everywhere.

    I did find a few articles regarding is_post_type_archive() not working which say: "The fix may be that the custom loop needs reseting. Add this after you close the loop."
    wp_reset_query();

    So I wonder if a query needs resetting somewhere, and what the likely candidate(s) would be.
    A clue may be that my code is affecting archive pages as well as pages that use mp_list_products shortcode.

    Thanks again for your time and interest in this topic!
    Best, Andy

  • Vinod Dalvi

    Hi Andy,

    The code that i have shared in my previous reply is working fine on my test site on the products list page here http://mysite.com/store/products/

    If it doesn't work for you then would you mind if I logged in to your site and did some troubleshooting? This might help get to the bottom of this faster. If this is ok, just grant me temporary admin access to your site by clicking "Grant Access" button in the WPMU DEV Dashboard Settings as described on the following page and reply on this thread after granting it?

    https://premium.wpmudev.org/manuals/wpmu-dev-dashboard-enabling-staff-login/

    Just wanted to confirm do you want to remove the specific products from the products list page here http://mysite.com/store/products/ and want to display it on other archive pages?

    The is_post_type_archive() function doesn't work on products list page because the Marketpress products list page is a virtual page. Technically it's not archive page or static page so we can't target it using is_post_type_archive() or is_page() functions.

    Regards,
    Vinod Dalvi

  • shelms1

    H Vinod,

    I just tried your code again on my local copy, and it does work on /store/products/ which I did not check before, my apologies for missing that one.

    However it does not work on product archive pages like category, tag, and any pages that utilize mp_list_products shortcode to list products.

    In short, I wish to make a product not appear in every archive or product list where it was previously presented before it was discontinued..

    I shall grant you access, and thanks again for your continued support.
    Best, Andy

  • shelms1

    Hi @Ashok,

    I thought it would be more efficient if the function only executes on 'product' pages, but perhaps it's too small an issue to chase down.

    I do want to see the discontinued product in the admin product and on the (single)product page itself, if a visitor lands on the product page via a google search -- otherwise I could just delete the product and have a 404 error.

    So to accomplish that I must use ` if ( is_admin() || $query->is_main_query() )
    return;` , correct?

    So the function as it stands now is:

    add_action( 'pre_get_posts', 'exclude_products_productlist', 1 );
    function exclude_products_productlist( $query ) {
            if ( is_admin() || $query->is_main_query() )
                    return;
            $query->set( 'post__not_in', array( 5316 ) );
    }

    Seems to work. Can it be more efficient?

    Thanks again for your interest, time and support!
    Best, Andy

  • shelms1

    Hello again @Ashok,

    Typing the word "single" in my previous entry gave me an idea, which I tested and seems to work. Thinking along the lines of what pages or views I wish to include, rather than exclude, I could also use is_singular(). Perhaps that's a bit more simple?

    add_action( 'pre_get_posts', 'exclude_products_productlist', 1 );
    function exclude_products_productlist( $query ) {
            if ( is_admin() || is_singular() )
                    return;
            $query->set( 'post__not_in', array( 5316 ) );
    }
    
    Best, Andy
  • Ash

    Hello @shelms1

    add_action( 'pre_get_posts', 'exclude_products_productlist', 1 );
    function exclude_products_productlist( $query ) {
            if ( is_admin() || is_singular() )
                    return;
            $query->set( 'post__not_in', array( 5316 ) );
    }

    The above code should not affect the store/product/ page. I have just tested again.

    Do you have any caching plugin installed? If yes, would you please delete cache and check again?

    Otherwise, would you please send me your ftp details and admin login details so that I can check?

    To send me details, please use our contact form: https://premium.wpmudev.org/contact/

    Select: I have a different question
    Subject: Attn-Ash (this ensures that it will be assigned to me)
    Details:
    1. Send all requested details
    2. Send a link of this thread so that I can track
    3. Send any other relevant link

    I will be happy to take a look :slight_smile:

    Cheers
    Ash

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.