I recently came across a known bug in WordPress 1.5.2 (well, at least it’s known to users; I can only assume that the dev community is also aware of it). Just wanted to post my fix here, in case anyone else finds it helpful.
Category exclusion is broken. The problem is that the category exclusion parameter (the 4th param) of next_post_link()
and previous_post_link()
is effectively ignored.
(next_post_link()
and previous_post_link()
are the new versions of the now-deprecated next_post()
and previous_post()
.)
A quick scan through the WordPress code indicates that the “category exclude” feature isn’t even implemented (at least not in a serious way) for next/previous_post_link. I haven’t spent much time perusing the WordPress code base, but from what I can tell, it seems that the relevant sections of these functions were never upgraded from an earlier WP version–one with a different schema; in particular, one with a different method of storing post-category relationships.
Here is how I fixed it in my installation (see warnings below before trying this at home):
1. Edit wp-includes/template-functions-links.php
. At approximately line 253 (in function get_previous_post
) [line 221 in WP1.5], you’ll see this:
$sql_exclude_cats = ''; if (!empty($excluded_categories)) { $blah = explode('and', $excluded_categories); foreach($blah as $category) { $category = intval($category); $sql_exclude_cats .= " AND post_category != $category"; } }
2. Replace that block with the following (beware of copy/paste errors, especially with respect to line breaks):
$sql_exclude_cats = ''; if (!empty($excluded_categories)) { ### ronr hack BEGIN ### # find ids of all posts in excluded cats $query = "SELECT post_id FROM $wpdb->post2cat WHERE category_id IN (" . str_replace(',', ',', $excluded_categories) . ')'; $excluded_post_rows = $wpdb->get_results($query); # build IN clause from those ids if (count($excluded_post_rows) > 0) { $sql_exclude_cats = ' AND ID NOT IN (' . intval($excluded_post_rows[0]->post_id); for ($i = 1; $i < (count($excluded_post_rows)); $i++) { $sql_exclude_cats .= ',' . intval($excluded_post_rows[$i]->post_id); } $sql_exclude_cats .= " )"; } ### ronr hack END ### }
(Note: instead of copy/pasting the above code, you can download it here.)
3. Now, make the same replacement in the corresponding block in get_next_post
, which is a little further down in the file.
Presumably, this bug will be fixed properly in an upcoming release, so now that I’ve got it working (albeit jury-rigged), I’m not going to spend any more time on it. If it doesn’t get fixed soon, perhaps I’ll clean it up and fold it into a plug-in (perhaps even as Asides plug-in).
My code does no error checking, and it assumes that the value of the exclude_categories parameter is not screwy. It’s provided as-is. I would never release code like this if it wasn’t intended to be used solely by me. If I wrote code like this at work, I’d deserve to be fired. Constructive suggestions for improvements are always welcome, but please don’t bitch to me about how it didn’t work for you, broke your blog, crashed your server, ruined your marriage, etc. Capisce?
Note too that I’ve changed the original interface; instead of separating excluded category ids with the word “and” (odd), it now expects a comma (not odd).
Anyway, good luck. And if you happen to find this useful, please let me know.
I discovered this subtle change when one of my unit tests mysteriously failed once I…
Exception chaining solves two problems in Python 2. 1. Swallowed Exceptions If, while handling exception…
Here's the recording of my talk "15 minutes w/ Beeswax: Safe Password Storage - How…
My presentation from the NYC Python Meetup: Python at Scale; Concurrency at Beeswax. Concurrent Python…
My BazelCon 2019 lightning talk, Python Dependencies The Right Way*, has been posted. Please excuse…
One of my favorite features of Python 3 is f-strings (Formatted String Literals). Each of…
This website uses cookies.
View Comments
Had some problems implementing the Previous_post_link and next_post_link exclusions (using Wordpress 2.8.6), until stumbling upon Steve M's syntax above - now works fine - thanks!
Personally, I had a whole array of problems with this and I only had 4 categories. The solution is still dodgy in Wordpress 2.3, but I got it working perfectly by:
<?php next_post_link($format='%link »', $link='%title', $in_same_cat
= false, $excluded_categories = 'X and X and X' ); ?>
It's explained in better detail on the wordpress codex here
As you will no doubt notice, the third parameter '$in_same_cat' is bogus and doesn't work if set to 'true.'
Thanks for this, Stewart. The problem subsists in 2.2.1. Your fix works for me but it's now line numbers 339 and 376 that need to be changed.
Sorry to spam you. :">
I figured out how to submit bug reports:
https://trac.wordpress.org/ticket/4304
Wait, I just figured out what the error is. For WP 2.1.3 the code in get_next_post and get_previous_post hasn't been tested, but most of the mistakes are harmless (for example $sql_exclude_cats is declared and never used).
There's a one line fix for WP2.1.3 to get this code to work. In both functions, this line (lines 294 and 331 in link-template.php):
$sql_cat_ids = " OR pc.category_ID = '$category'";
should be changed to
$sql_cat_ids .= " OR pc.category_ID = '$category'";
(changed = to .=)
Where do I submit WP bug reports & fixes. Can I submit a patch myself?
I'm trying to get this feature (the fourth parameter to get_next_post) to work in WP 2.1.3 and it still seems to be broken. I looked at the WP code (now in wp-includes/link-template.php) and they've changed it, but it still doesn't work for me.
If I use
get_next_post('%link', '%title', FALSE, '1 and 2');
then posts in category 2 are ignored, but not those in 1. It's quite annoying!
I looked at the code, but at cursory inspection I can't see what's wrong with it. Have you managed to get this feature to work in v2.1.3?
Excellent! I'm happy to [finally!] be obsolete. :)
I just gave it a shot and it does work fine!! So while your hack helped me out for a long time (again thanks for providing it!) with 2.1 it became obsolete. ;)
good question. i'm not sure yet; i'm waiting for the bugs to be shaken out before i switch to the 2.1 branch. (but maybe someone else on this thread has installed 2.1 and can tell us?)
Hi Ron,
Thanks for the "hack" - it really works like a charm and has been ever since I implemented the Sideblog plugin on top of WP2.03. Would you know whether the faulty core code has been fixed in WP2.1?
Thanks,
Oliver