Hey everybody,
seeing as this is a notorious issue, I thought I'd share a function of mine that solved the problem.
The Problem
As many of you probably know, the default previous_post_link() and next_post_link() functions of Wordpress are frustratingly limited, even with the following two parameters:
in_same_term - Indicates whether previous/next post must be within the same taxonomy term as the current post. [...] If the post is in both the parent and subcategory, or more than one term, the previous post link will lead to the previous post in any of those terms.
-> Even when activated, this means that previous/next post links cannot be restricted to just the immediate child category and will typically go all over the place.
Excluded terms - Array or a comma-separated list of numeric terms IDs from which the next post should not be listed.
-> Though exluding all the parent categories with this in combination with the above seems like a solution at first, Wordpress unfortunately interpretes this parameter to exlude all posts assigned to the categories. Example: Imagine your hierarchy is "Movies -> Science-Fiction -> Cyberpunk" and you always tag your "Cyberpunk"-Posts in all the parent categories as well. By exluding "Movies" and "Science-Fiction" to restrict the query to just "Cyberpunk", Wordpress will exlude everything instead.
You could tag your posts with the lowest child category only and then exclude its parents, which should work, of course. However, there's often a reason you don't want to do so, in which case, the following should help.
Prev/Next-Post-Navigation in the lowest child category
This function will return a multidimensional array with the structure: $results[x][y], where x is the direction (0 = previous post, 1 = next post) and y is the post data (0 = post title, 1 = post permalink). So for example, $results[1][0] would return the title of the next post. When there is no previous/next post, the array will return an empty string as data.
function lowest_category_post_navigation() {
// Finding the "lowest" child category
$categories = get_the_category();
$lowest_category = $categories[0];
foreach($categories as $i => $testcategory)
{
if($testcategory->parent == $lowest_category->cat_ID)
{
$lowest_category = $testcategory;
}
}
// Some placeholders for the loop
$currentpost_date = get_the_date() . " " . get_the_time();
$currentposttrigger = false;
$prevposttitle = "";
$prevpostlink = "";
$nextposttitle = "";
$nextpostlink = "";
// Loop to fetch all posts of the lowest category in a query
// and to save the titles/links of posts adjascent to current post
$args = array('cat' => $lowest_category->cat_ID,
'orderby' => 'date',
'order' => 'DESC');
$category_query = new WP_Query($args);
if ( $category_query->have_posts() ) : while ( $category_query->have_posts() ) : $category_query->the_post();
$querypost_date = get_the_date() . " " . get_the_time();
if ($currentposttrigger == true)
{
$prevposttitle = get_the_title();
$prevpostlink = get_permalink();
$currentposttrigger = false;
}
if ($currentpost_date === $querypost_date)
{
$currentposttrigger = true;
$nextposttitle = $temp_nextposttitle;
$nextpostlink = $temp_nextpostlink;
}
$temp_nextposttitle = get_the_title();
$temp_nextpostlink = get_permalink();
endwhile;
else:
// no posts found
endif;
wp_reset_postdata();
// Saving results into array
$results = array
(
array($prevposttitle, $prevpostlink),
array($nextposttitle, $nextpostlink)
);
return $results;
}
Basically what this function does is find the deepest child category of the current post, query that and only that category by date and retrieve the title and link of the previous and next posts.
Hope this helps!