Skip to main content
12 of 14
deleted 628 characters in body

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?


EDIT: ATTEMPT 1

Milo pointed me to an answer that suggested to add this to my functions.php:

function my_404_override() {
  global $wp_query;
  
  if (is_author()) {
    status_header( 200 );
    $wp_query->is_404 = false;
  }
}
add_filter('template_redirect', 'my_404_override');

But it still shows me a 404 error. If I remove the if clause, then it leads me to the index.php which is not reeeally what I intended. My guess is that

  1. either this code gets executed before WordPress knows what template it's dealing with (trying to execute get_current_template(true) in there throws an "Undefined function" error)
  2. OR because $wp_query->is_404 is true by the time this code is run, it doesn't attempt to load the author.php template.

Pasting the code directly to the template didn't work either, even if it's just these three lines pasted before get_header();:

global $wp_query;
status_header( 200 );
$wp_query->is_404 = false;

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" version of joints_page_navi() for my $secondloop to work (or not)
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."";
}