I have a custom post type "Scholars" that has an archive. I want to sort by a custom meta field called "year", I'm doing this with pre_get_posts:

add_action('pre_get_posts', 'my_queries');
function my_queries($query)
  if (!$query->is_main_query()) return;

  if ($query->query['post_type'] == 'scholars') {
    $query->set('posts_per_page', -1);
    $query->set('meta_key', 'year');
    $query->set('orderby', 'meta_value');

This works fine in the archive page (the main listing), but the next_post_link and previous_post_link are not in sync in the single post. They are still sorted by date and not by custom "year".

I have a custom query on the single page using WP_Query to show related posts, but I tried removing it and still does not work.

This is the archive page:

<div class="large-12 columns">
    if (have_posts()) {
      while (have_posts()) {
        // this just loads an <article>
        get_template_part('content', 'scholars');
    } else {
      echo '<h2>Nothing found.</h2>';

And this is the single page:

<?php the_post() ?>

<div class="large-12 columns">
  <nav class="scholars-navigation">
    <span class="prev"><?php previous_post_link() ?></span>
    <h2><?php the_title() ?></h2>
    <span class="next"><?php next_post_link() ?></span>

<div class="large-3 columns scholar-info">
  <img src="<?php the_field('photo') ?>" alt="" />
  <h3><?php the_field('year') ?> Scholar</h3>

Any ideas why it won't work?

Edit: After looking at other related answers seems like this is not possible with the built-in function out of the box, found this plugin but I'm open to any solution.

Edit: Pfff, it doesn't even work with that plugin, don't know what the issue is:


1 Answer 1


The next_post_link() and previous_post_link() functions do not use the same query that 'pre_get_posts' affects. They use their own custom queries. You have to use other filters to affect them.

Utimately, the get_adjacent_post() function does the bulk of the work for the next_post_link() and previous_post_link() functions.

Here is part of that function:

$adjacent = $previous ? 'previous' : 'next';
$op = $previous ? '<' : '>';
$order = $previous ? 'DESC' : 'ASC';

$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories );
$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );
$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );

To change the sort order for the next post use the 'get_next_post_sort' filter and use the 'get_previous_post_sort' filter to change the sort for the previous link.

You can see from this code snippet that the value in $order in the original query depends on which filter you are writing code for.

Sorry, I don't know SQL well enough to write that part of the query.

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.