Skip to main content
7 of 14
Added code as requested

Intentionally exceed max_num_pages on main query without getting 404?

In author.php I have two loops: the default main loop that gets all posts from that author, and another custom WP_Query called $secondloop. Both queries have posts_per_page set to 3. Now I'd like to paginate both query results.

For this I've added an argument to $secondloop = new WP_Query($args):

"paged" => (get_query_var('paged')) ? get_query_var('paged') : 1;

(read: set this query's page to the same page as the main query's).

THE PROBLEM:

  • If the main loop gives me 5 posts and my $secondloop gives me 2, then calling page 2 works no problemo. It shows me the remaining 2 posts from the main loop and none from my $secondloop (since it doesn't go inside while ($secondloop->have_posts())).

  • BUT if the main loop has 2 posts and $secondloop has 5, then calling page 2 results in 404 :( I obviously want $secondloop's remaining 2 posts instead.

Changing anything inside the author.php template doesn't help, because it seems that no PHP code in there is executed any more, once WordPress detects that max_num_pages from the main loop is exceeded.

How can I "override" that behaviour?


THE CODE:

author.php (just the useful bit)

<?php if (have_posts()) { ?>
    <div class="row archive-grid">
        <?php while (have_posts()) : the_post();
            include(locate_template('parts/loop-archive-grid.php'));
            endwhile; ?>
    </div>
<?php }

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$secondloop = new WP_Query(array(
    "post_type"      => "musikalbum",
    "posts_per_page" => 3,
    "author_name"    => get_query_var('author_name'),
    "paged"          => $paged
));

if ($secondloop->have_posts()) { ?>
    <div class="row archive-grid">
        <?php while ($secondloop->have_posts()) : $secondloop->the_post();
            get_template_part( 'parts/loop', 'album-grid' );
        endwhile; ?>
    </div>
    <?php author_page_navi( $loop );
} else {
    joints_page_navi();
} ?>

Setting the posts_per_page for my main query in my functions.php

function my_post_queries( $query ) {
  if (!is_admin() && $query->is_main_query()){
    if (is_author()){
      $query->set('posts_per_page', 3);
    } else {
      $query->set('posts_per_page', 9);
    }
  }
}
add_action( 'pre_get_posts', 'my_post_queries' );

And here are the pagination functions used from my JointsWP4 starter theme:

<?php // This function was standard from my JointsWP4 starter theme...
function joints_page_navi($before = '', $after = '') {
  global $wpdb, $wp_query;
  $request = $wp_query->request;
  $posts_per_page = intval(get_query_var('posts_per_page'));
  $paged = intval(get_query_var('paged'));
  $numposts = $wp_query->found_posts;
  $max_page = $wp_query->max_num_pages;
  //...except for this line, since author_page_navi uses the same logic:
  page_navi_logic( $posts_per_page, $paged, $numposts, $max_page );
}

// A "hacked together" version of joints_page_navi() that takes my $secondloop and gets the maximum values of both queries
function author_page_navi( $loop ) {
  global $wpdb, $wp_query;
  $request = $wp_query->request;
  $posts_per_page = max(intval($wp_query->posts_per_page), intval($loop->posts_per_page));
  $paged = intval(get_query_var("paged"));
  $numposts = max($wp_query->found_posts, $loop->found_posts);
  $max_page = max($wp_query->max_num_pages, $loop->max_num_pages);
  page_navi_logic( $posts_per_page, $paged, $numposts, $max_page );
}

function page_navi_logic( $posts_per_page, $paged, $numposts, $max_page ) {
  if ( $numposts <= $posts_per_page ) { return; }
  if(empty($paged) || $paged == 0) {
    $paged = 1;
  }
  $pages_to_show = 3;
  $pages_to_show_minus_1 = $pages_to_show-1;
  $half_page_start = floor($pages_to_show_minus_1/2);
  $half_page_end = ceil($pages_to_show_minus_1/2);
  $start_page = $paged - $half_page_start;
  if($start_page <= 0) {
    $start_page = 1;
  }
  $end_page = $paged + $half_page_end;
  if(($end_page - $start_page) != $pages_to_show_minus_1) {
    $end_page = $start_page + $pages_to_show_minus_1;
  }
  if($end_page > $max_page) {
    $start_page = $max_page - $pages_to_show_minus_1;
    $end_page = $max_page;
  }
  if($start_page <= 0) {
    $start_page = 1;
  }
  echo $before.'<nav class="push-down"><ul class="pagination">'."";
  if ($start_page >= 2 && $pages_to_show < $max_page) {
    $first_page_text = __( 'Erste...', 'jointswp' );
    echo '<li><a href="'.get_pagenum_link().'" title="'.$first_page_text.'">'.$first_page_text.'</a></li>';
  }
  echo '<li>';
  previous_posts_link( __('Back', 'jointswp') );
  echo '</li>';
  for($i = $start_page; $i  <= $end_page; $i++) {
    if($i == $paged) {
      echo '<li class="current"> '.$i.' </li>';
    } else {
      echo '<li><a href="'.get_pagenum_link($i).'">'.$i.'</a></li>';
    }
  }
  echo '<li>';
  next_posts_link( __('Forward', 'jointswp'), $max_page );
  echo '</li>';
  if ($end_page < $max_page) {
    $last_page_text = __( 'Last...', 'jointswp' );
    echo '<li><a href="'.get_pagenum_link($max_page).'" title="'.$last_page_text.'">'.$last_page_text.'</a></li>';
  }
  echo '</ul></nav>'.$after."";
}