Pagination not working on custom post format query on page

Hi, I have a page called page-media-list.php (Media List). It queries all the posts that are format gallery or video (a list of media posts). My pagination works on archives and taxonomy queries, just not here for some reason.

But pagination is not working. Here is my page-media-list.php code:

<?php


 $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
  $medialist = new WP_Query(
    array(
      'post_type' => array('post', 'advertorials'),
      'posts_per_page' => 15,
      'tax_query' => array(
        array(
          'taxonomy' => 'post_format',
          'field' => 'slug',
          'terms' => array( 'post-format-gallery', 'post-format-video' ),
        )
      ),
      'paged' => $paged
    )
  );
?>
<?php if ($medialist->have_posts()): while ($medialist->have_posts()) : $medialist->the_post(); ?>
  <?php get_template_part('templates/content-medialist', get_post_type() != 'post' ? get_post_type() : get_post_format()); ?>
<?php endwhile; ?>
  <?php get_template_part('templates/page-navi'); ?>
<?php endif; ?>
<?php wp_reset_query(); ?>

And the pagination is a separate file, templates/page-nav, which is this:

<div class="article-navigation">
<?php Roots\Sage\Extras\sage_page_navi(); ?>
</div>

and calls this function in sage extras.php

function sage_page_navi() {
  global $wp_query;
  $big = 999999999; // need an unlikely integer
  $pages = paginate_links( array(
  'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
  'format' => '?paged=%#%',
  'current' => max( 1, get_query_var('paged') ),
  'total' => $wp_query->max_num_pages,
  'prev_next' => false,
  'type'  => 'array',
  'prev_next'   => TRUE,
  'prev_text'    => '&larr;',
  'next_text'    => '&rarr;',
  ) );
  if( is_array( $pages ) ) {
    $paged = ( get_query_var('paged') == 0 ) ? 1 : get_query_var('paged');
    echo '<ul class="pagination pagination-lg">';
    foreach ( $pages as $page ) {
      echo "<li>$page</li>";
    }
    echo '</ul>';
  }
}/* end page navi */
add_filter('sage_page_navi', __NAMESPACE__ . '\\sage_page_navi');

I have run into this problem as well. Let me ask you, on your post archives & taxonomy pages are you using a new WP_Query? I expect the answer is no.

I once tried creating a new WP_Query that excluded sticky posts on my homepage and it broke the pagination.

Not sure why this happens, I’ll definitely check back if I find out more.

1 Like

I ran into this a week or so ago - it seems that the issue is that pagination bases its output on the main query object. Custom queries are based on a different loop, hence custom query, so the main query object doesn’t apply.

Double check this because it’s late and I’m tired, but something like this should work for you -

<?php
// Define custom query parameters
$medialist_args = array(
  // your query paramaters
);

// Get current page and append to custom query parameters array
$medalist_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;

// Instantiate custom query
$medalist_query = new WP_Query( $medalist_args );

// Pagination fix
// stash main query object
$temp_query = $wp_query;
// wipe it
$wp_query   = NULL;
// replace it
$wp_query   = $medalist_query;

// run the loop
  if ($medialist_query->have_posts()):
    while ($medialist_query->have_posts()) : $medialist_query->the_post();

      get_template_part('templates/content-medialist', get_post_type() != 'post' ? get_post_type() : get_post_format());

    endwhile;
  endif;

// reset post data   
wp_reset_postdata();

// get pagination
get_template_part('templates/page-navi');

// Restore main query object
$wp_query = NULL;
$wp_query = $temp_query;

// Credit - Chip Bennett
// @url http://wordpress.stackexchange.com/questions/120407/how-to-fix-pagination-for-custom-loops

Chip Bennet gives a pretty good breakdown and explanation here - http://wordpress.stackexchange.com/questions/120407/how-to-fix-pagination-for-custom-loops

Hope that helps!

1 Like

Perhaps this doesn’t apply to you guys, but in recent years I’ve gotten away from creating a page and building my own query. It’s more proficient and a lot less work.

Generally, I set has_archive to true. This basically covers the CPT, and you can also use taxonomy terms to sort posts as well.

You style the CPT with archive-cpt.php. Any extra query parameters use the pre_get_posts filter.

Profit because you no longer have to deal with strange pagination issues. You also use the main query correctly

1 Like

Definitely, I try to use archive pages wherever possible because it’s so much easier. A lot of times I run into issues where the design calls for some sort of user defined content at the top of the page, that’s generally where I end up making some sort of page template.

Yea, I always try to use archive pages, but this is an archive to post formats, so I had to use a page to write a query. But I got it to work as such (see below). Thanks for the help everyone!

<?php
$paged = get_query_var('paged') ? get_query_var('paged') : 1; //The magic, ternary if statement
$args  = array(
    'posts_per_page' => 15,
    'post_type' => array('post', 'advertorials'),
    'tax_query' => array(
        array(
          'taxonomy' => 'post_format',
          'field' => 'slug',
          'terms' => array( 'post-format-gallery', 'post-format-video' ),
        )
      ),
    'paged' => $paged
);
query_posts($args);
if ( have_posts() ) : while ( have_posts() ) : the_post();
?>
  <?php get_template_part('templates/content-archive'); ?>
<?php endwhile; ?>
  <?php get_template_part('templates/page-navi'); ?>
<?php endif; ?>
1 Like

I’ve been having a problem with Sage or WP borking my pagination on a Custom Home Page (with a custom WP_query loop). The problem seemed to be that the pages would cache, so every page would just link to ‘Page 2’.

Nothing seemed to work, but after I created a new base template (base-front-page.php) and removed the <?php // include Wrapper\template_path(); ?> and replaced it with basic includes such as :

<?php  include( TEMPLATEPATH . '/templates/page-header.php' ); ?>
<?php  include( TEMPLATEPATH . '/templates/mypage.php' ); ?>

things started to work. Not entirely sure why, but perhaps this could help someone.

That shouldn’t work / shouldn’t be the solution

I’ve just opened up the file again…

Seems it wasn’t the: use Roots\Sage\Wrapper;

But rather the:
<?php include Wrapper\template_path(); ?>

Which seemed to be causing me problems. Once I removed that and tried basic includes, ie.

<?php include( TEMPLATEPATH . '/templates/page-header.php' ); ?>
<?php include( TEMPLATEPATH . '/templates/mypage.php' ); ?>

The pagination works as it should.

Using <?php include( TEMPLATEPATH is not the appropriate solution to your problem. You have other underlying issues if include Wrapper\template_path(); wasn’t working as expected for you

You can simply do this using WP-Query class and display posts with pagination. This code is for custom pagination.

 <?php
/**
* Template Name: Custom Page
*/
get_header(); ?>

<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
  'posts_per_page' => 4,
  'paged' => $paged
);
$custom_query = new WP_Query( $args );
?>
          <!----start-------->
<div class="wrap">
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">

<?php
   while($custom_query->have_posts()) :
      $custom_query->the_post();
?>
       <div>
        <ul>
         <li>
           <h3><a href="<?php the_permalink(); ?>" ><?php the_title(); ?></a></h3>
        <div>
          <ul>
        <div><a href="<?php the_permalink(); ?>"><?php the_post_thumbnail('thumbnail'); ?></a></div>
          </ul>
          <ul>
        <p><?php echo the_content(); ?></p>
          </ul>
        </div>
        <div>
          </li>
        </ul>
          </div> <!-- end blog posts -->
       <?php endwhile; ?>
      <?php if (function_exists("pagination")) {
          pagination($custom_query->max_num_pages);
      } ?>
</main><!-- #main -->
</div><!-- #primary -->
</div><!-- .wrap -->
          <!----end-------->
        <?php get_footer();

Reference: https://www.wpblog.com/use-wp_query-to-create-pagination/

Hello, I have the same issue. I tried to create new post type with 'has_archive' => true, but it didn’t help me. Here is my code:
1. Register post

  register_post_type( 'events', [
        'labels'             => [
            'name'               => 'Event',
            'singular_name'      => 'Event',
            'add_new'            => 'Add new',
            'add_new_item'       => 'Add new Event',
            'edit_item'          => 'Edit Event',
            'new_item'           => 'New Event',
            'view_item'          => 'View Event',
            'search_items'       => 'Find Event',
            'not_found'          => 'Event not found',
            'not_found_in_trash' => 'Event not found in trash',
            'parent_item_colon'  => '',
            'menu_name'          => 'Events'
        ],
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => [ 'slug' => 'events', 'with_front' => false ],
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'custom-fields'      => true,
        'menu_position'      => 5,
        'supports'           => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'tags', 'category' ]
    ] ); 

register_taxonomy(
        'status',
        'events',
        array(
            'label'        => __( 'Status' ),
            'rewrite'      => [ 'slug' => 'status' ],
            'hierarchical' => true,
            'has_archive'  => true,
        )
    );
}

*2. Template
`{{–
Template Name: Template Events
–}}
@php
$paged = get_query_var(‘paged’) ? get_query_var(‘paged’) : 1;
$taxonomyName = ‘status’;
$currentStatusSort = isset($_GET[$taxonomyName]) ? $_GET[$taxonomyName] : ‘upcoming-events’;
$term = get_term_by(‘slug’, $currentStatusSort, $taxonomyName);

$args = [
‘post_type’ => ‘events’,
‘post_status’ => ‘publish’,
‘taxonomy’ => ‘status’,
‘posts_per_page’ => 10,
‘paged’ => $paged,
‘tax_query’ => [
[
‘taxonomy’ => ‘status’,
‘field’ => ‘term_id’,
‘terms’ => $term->term_id
]
]
];
$events = new WP_Query( $args );
@endphp

@extends(‘layouts.content’)
@section(‘content’)

{!! App::title() !!}

{{ $term->name }}

@while(have_posts()) @php the_post(); the_content(); @endphp @endwhile

@include('partials.menu-nav')
@if (!$events->have_posts())
Sorry, we don't have upcoming events. Check our past events or check our resources
@else
    @while ($events->have_posts())
      @php
        $events->the_post();
      @endphp
      @include('partials.content.content-'.get_post_type())
    @endwhile

    {!! get_the_posts_navigation([
      'screen_reader_text' => '',
      'prev_text'          => 'Older events',
      'next_text'          => 'Newer events'
    ]) !!}

    @php
      wp_reset_postdata();
    @endphp
  @endif
</div>
@endsection`

Thanks for this. Pretty new so have a follow up to this older thread (haven’t found a more recent rabbit hole that looks apt). Would this be better served as a public function in App, or in a blade template to separate from the get_posts() of the current page contents?

How to output this into a component, to show previous/next links is my end goal.

Hi there! I think that’d probably be best served as a function in App, where you’d make its output available to one of your blade templates.

Have a read through this thread if you’d like, here’s where I had my OMG WOW moment with templating.

Hope that helps a bit!