1

I have an issue with WP_Query returning the same post I'm on in my results. At the bottom of my post page, I have this code:

//Displays 3 Recent Posts:

<section id="related-posts">
        <?php

        //Start Related Posts Logic

        $args = array(
            'post_type' => 'post',
            'posts_per_page' => 3,
        );

        $chord_melody_blog_query = new WP_Query($args);
        
        $countBlog = 1;

        while ($chord_melody_blog_query->have_posts()) : $chord_melody_blog_query->the_post();
            $blogId = $post->ID;
            $thumbnail = 'post-thumb';
            $get_featured_image_link = wp_get_attachment_image_src(get_post_thumbnail_id($blogId), $thumbnail, false, '');

//Echoes out the posts:
            echo '<div class="related-post">
                    <a href="' . get_permalink($blogId) . '"><img src="' . $get_featured_image_link[0] . '"></a>
                    <div class="related-post-title">
                    <h5>' . get_the_title() . '</h5>
                    <a href="' . get_permalink($blogId) . '" role="link" title="Read Full Lesson">View Lesson</a>
                    </div>
                </div>
                ';
            $countBlog++;

        endwhile;

        wp_reset_postdata();

        ?>

The issue is, If I'm on the most recent post (let's call it "All about Carrots"), the results would be "All About Carrots", "Second Recent Post", "Third Recent Post".

How can I avoid the post that I'm currently viewing from populating the results?

Thanks!

1

There are 2 methods. The ultra slow method, and the fast method

The Ultra Slow Method

This method is easy to implement, but can place a massive load on the database, and can cause major performance issues ( as well as severely reduce the number of people who can access your site at the same time ).

This is the post__not_in argument. I do not recommend using this. I mention it only for completeness, and because people unaware of the performance hit will recommend it.

Why is This So Terrible?

Database queries are built around searching for what you want, not what you do not want.

So if you exclude posts at the database level, the database will sometimes copy the entire posts table into memory, remove the rows you wanted to exclude, then perform the query. This is extremely slow and expensive.

In my time working on enterprise WordPress hosting I've seen NOT IN type queries cripple sites, either by bringing them down or slowing them to unusable levels. Removing it caused dramatic improvements.

The danger is that when testing these queries out on a smaller test site, they don't look slow, not great, but okay... Add in multiple users hitting the site at the same time, and bump up the size of the posts and meta tables, and that okay looking query grows to monstrous proportions.

The Fast Method

Ask for 4 posts instead and filter out the posts you don't want in PHP.

This method is super fast.

For example:

$args = [
    'posts_per_page' => 4,
];

$q = new WP_Query($args);
$count = 0;
while ( $q->have_posts() ) {
    $q->the_post();
    if ( $excluded_id === get_ID() ) {
        continue;
    }
    $count += 1;
    if ( $count > 3 ) {
        break;
    }

    //  ......
}

Notice that if we've already shown 3 posts, or if the post we showed was excluded then we break/continue.

A Final Note

The above also applies to any argument that ends in __not_in, they all have terrible performance. Another solution that doesn't apply to this use case is to use data to solve the problem. For example instead of adding a checkbox to hide a post from the homepage, add a term named show_on_homepage that's added by default.

Also note that your while loop needs to be wrapped in an if statement checking if have_posts returns true. If you do not then there is a bug, if no posts are found then wp_reset_postdata() is called when there is no post data to reset, interfering with any surrounding post loops.

The code in the question is also missing escaping and as a result is vulnerable to HTML injection attacks.

1
  • 1
    Hey Tom sorry it took me so long to get back to you. This solved the issue, and thanks for providing some background and extra explanations! These really make sense. Thanks again!
    – sackadelic
    Feb 15 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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