1

I’m using the following code to hide certain posts by post ID on the front page (as per https://michaelkummer.com/technology/howto-hide-posts-pages-in-wordpress/ and on the WordPress Codex https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts)

function exclude_single_posts_home($query) {
     if ($query->is_home() && $query->is_main_query()) {
          $query->set('post__not_in', array(69489, 69177,68878,68736));
      }
}

This code works well, but unfortunately I'm using a few other plugins on my main page (a most popular posts widget as well as flexslider to feature posts) and any posts that I hide will still show up in those plugins.

Is there a way to hide posts on the front page and also prevent it from being displayed on plugins on the same page?

I'm using Wordpress 5.0.3 and the theme Hueman.

Hope the question makes sense! Any help is greatly appreciated 🙂

1 Answer 1

1

If you want to hide certain posts from all queries on the front page, then remove the conditions you're using and check is_front_page() instead:

function exclude_single_posts_home($query) {
     if (is_front_page()) {
          $query->set('post__not_in', array(69489,69177,68878,68736));
      }
}

Normally checking the global state is the incorrect way to filter queries (what you'd originally done is the normal correct way), but in your case you actually do want to filter all queries based on the global state, so it's appropriate.

Just be aware that post__not_in has poor performance, especially if you apply it to multiple queries at once. You might want to consider an alternative approach, like using a custom field or custom taxonomy that you can apply to posts that you want to hide. Queries based on those would be more efficient.


Having added a hide field to posts using Advanced Custom Fields, you can filter out these posts by setting a meta query:

function exclude_single_posts_home($query) {
    if (is_front_page()) {
        $original_meta_query = $query->get( 'meta_query' );

        $new_meta_query = [
            'relation' => 'OR',
            [
                'key'     => 'hide',
                'compare' => 'NOT EXISTS',
            ],
            [
                'key'     => 'hide',
                'value'   => '1',
                'compare' => '!='
            ],
        ];

        if ( $original_meta_query ) {
            $meta_query = [
                'relation' => 'AND',
                $original_meta_query,
                $new_meta_query
            ];
        } else {
            $meta_query = $new_meta_query;
        }

        $query->set('meta_query', $meta_query );
    }
}

The code for this is quite a bit more complicated, for a couple of reasons:

  • Since you're only just adding the field for the first time, there will be posts that do not have a positive or negative value for hide, so we need to treat posts without this field at all as being not hidden. That's what the NOT EXISTS query is for. Given this complication I'm not actually certain if the performance will be an improvement. You might want to install the Query Monitor plugin and compare the performance of each.
  • I was relatively confident that no existing queries on the front page had a value for post__not_in, so didn't bother handling the possibility of conflicts. However, it is more likely that some of the existing queries already have a meta_query set, so this code includes logic that adds the new meta query for hiding posts to any existing queries of they exist, rather than replacing them.
8
  • Thank you so much! It works perfectly. I'll look into applying a custom field/taxonomy - thanks for the suggestion.
    – distinctly
    Commented Mar 7, 2019 at 11:27
  • "post__not_in has poor performance" - why? It becomes a where ID not in (...) clause in SQL, and ID is an indexed column in wp_posts, so that ought to be efficient.
    – Rup
    Commented Mar 7, 2019 at 11:53
  • It does, and that's the source of the performance issues, to my understanding. Commented Mar 7, 2019 at 11:59
  • Hi Jacob/Stackexchangers, thank you once again for your help. Just following on from the above, I'm looking into applying a custom field for the query above, and have downloaded the Advanced Custom Fields plugin (advancedcustomfields.com) and have created a true/false field named 'hide' for the posts that i'd like to hide. I'm a bit stumped on how to modify the code above to capture all posts with a value of true for the custom 'hide' field - would be grateful for any help, or if there's an even better/simpler way to do this for a coding newbie like myself. Thank you :)
    – distinctly
    Commented Mar 7, 2019 at 12:07
  • I've updated my answer. Commented Mar 7, 2019 at 12:24

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.