• Resolved Annekee

    (@annekee)


    Below my single post is a previous_post_link/next_post_link navigation. I have a post (ID=1) I want to exclude from that navigation. I managed to exclude the post everywhere else (catalog, search, sitemap) but this keeps me awake at night.

    I already tried a custom query, with ‘post__not_in’ => array(1)) but to no avail.
    Then I tried the plugin WP HIde Post, and it works fine, except for hiding the post in that navigation.

    Any ideas would be more than welcome!

Viewing 8 replies - 1 through 8 (of 8 total)
  • Moderator bcworkz

    (@bcworkz)

    The post links create their own SQL query, that is why a custom query doesn’t work. The post links depend on get_adjacent_post() to determine the next/previous link. It offers the "get_{$adjacent}_post_excluded_terms" filter to exclude unwanted posts. $adjacent will be either ‘next’ or ‘previous’. Your callback is passed an array of excluded post IDs (probably empty). Add your exclusion IDs to the array and return the modified array.

    Thread Starter Annekee

    (@annekee)

    Thank you very much bcworks! It’s pretty advanced stuff for me, but at least now I know where and with what I can solve it. Thanks!

    Moderator bcworkz

    (@bcworkz)

    You’re welcome.

    Unfortunately, I just realized that the filter is not exactly as I described. It’s a new filter. In my excitement in it’s discovery, I didn’t look closely enough, I saw ‘post_excluded’ and thought “Eureka!” The fact that ‘term’ was in the mix didn’t register. This filter excludes taxonomy term IDs, not post IDs šŸ™ My apologies.

    The correct filter is "get_{$adjacent}_post_where" (applied from same function). This one is more complex because there’s no simple array to manipulate, you need to manipulate the actual SQL WHERE clause. Specifically, replace WHERE with WHERE p.ID<>1 AND.

    Now that I’ve totally overwhelmed you, I hope you can still believe me when I say this will end up being not nearly as bad as it sounds. Maybe 6 lines of code. Sure, it’ll take a some research and patience, but if you managed custom queries, you can do this too!

    Thread Starter Annekee

    (@annekee)

    Hi bcworkz, thanks for that. I researched but I’m afraid I haven’t got the knowledge to solve this problem. I’ve read quite some bits and pieces of code on the internet, but I still don’t know how to practically implement it in my template. Yes, I found out about the term ID’s, and most solutions available are about excluding a category, instead of a post. Still, you inspire me to give it another try.

    I was wondering, instead of excluding a post ID, maybe it is easier to take the post title, slug, or date?

    If all else fails, I think I’m going to put the post in another category, and hide that category from the website…

    Moderator bcworkz

    (@bcworkz)

    "get_{$adjacent}_post_where" allows one to directly alter the SQL WHERE clause, so it is extremely powerful in its ability to customize the query to find the next/previous post. You can alter this clause to exclude posts, include posts, and do whatever else one does with SQL queries. This includes using various columns of various tables to qualify results, including title, slug, date, etc. Since all these criteria work off the same filter, I wouldn’t say any one is easier or more difficult, just whatever is most convenient would be the one to use.

    Besides the post where filter and the previous excluded terms filter, there is another filter for the JOIN clause, so you could link in other tables besides those already used to construct quite elaborate criteria. This is no doubt beyond your personal ability, my intent is merely to merely impress upon you that there are few limitations regarding the alteration of this function to someone knowledgeable enough.

    Using a particular category to exclude certain posts is actually a good idea because it’ll be easier to exclude other posts in the future. Merely assign the exclusion category. If we were to stick with the post where filter, any future post that needs exclusion would need to be added to the custom PHP code, a much more daunting task than assigning a category!

    The catch is that excluding the category from the next/previous post template tags still requires hooking a couple filters and altering the passed value. There is another possibility with this approach though. It entails creating your own custom template tags that use get_adjacent_post() just like the core template tags (next_post_link() etc.), except they make use of the excluded terms parameter of the function itself, instead of relying on the filter.

    This approach may be desirable because most of the custom code is copy/paste, just renaming the functions and using that one parameter. But honestly, using the excluded terms filter is simpler once you understand the concept. Understanding filters is difficult to grasp at first. At some point the concept sinks in and you’ll think “Oh, I see! It’s so simple!” Filters (and actions) are integral to customizing many aspects of WordPress, so it’s worth the time to study these in detail until they are fully understood.

    Aside from constructing a filter callback function and adding it to two filter hooks, the only thing the callback really needs to do is this: $passed_array[] = $term_id;

    More on filters and actions can be found here: https://developer.wordpress.org/plugins/hooks/

    The reference is for plugins, but filter hooks can be right on the template if that is the only time the hook is required. Hooks can also be on functions.php of a child theme. Child themes are strongly recommended any time you customize a theme template (or anything else about the theme) so your changes are protected should the theme be updated.

    Thread Starter Annekee

    (@annekee)

    Thanks again for your time and your patience! Some of your explanation needs study on my part, some of it I am already familiar with. Of course I am using a child theme šŸ™‚ and my functions.php is already quite heavy. I am also a little familiar with sql, so that comes in handy.
    This particular child theme is from Mystile/Woocommerce. I like the robust shop coding, but the templating system is way over the top…

    Thread Starter Annekee

    (@annekee)

    Victory! It’s much much simpler, this works for me (in local developement):

    <nav id="post-entries" class="fix">
      <div class="nav-prev fl">
        <?php
        // address the previous post
        $adjacent_post = get_adjacent_post(true,'',true);
        // if the previous post ID is not 1
        if ( $adjacent_post->ID != 1 ) { ?>
          <?php previous_post_link( '%link', '<span class="meta-nav">←</span> %title' ); ?>
        <?php } ?>
      </div>
      <div class="nav-next fr">
        <?php next_post_link( '%link', '%title <span class="meta-nav">→</span>' ); ?>
      </div>
    </nav>

    * Since I’m excluding the oldest post (with ID=1) I only need to address the previous_post_link, and simply not show it. To skip a post, that would need another approach.

    Moderator bcworkz

    (@bcworkz)

    Awesome! Yes, I was assuming you would want to skip any undesirable post. If it meets your needs then that is all that matters. It’s better to go with code you understand than paste together a bunch of crap you don’t understand šŸ™‚

Viewing 8 replies - 1 through 8 (of 8 total)

The topic ‘How exclude one post from prev/next in single post?’ is closed to new replies.