I am trying to figure out a way to make the_posts_pagination or any alternative output numeric post navigation for a custom query.
but it doesn't seem to work, I don't know if I am doing anything wrong would appreciate suggestions and solutions thanks in advance
My Code
<?php global $query_string; // required
$posts = query_posts($query_string.'&posts_per_page=3&order=ASC'); ?>
<div class="main-post-loop">
<div class="big-thum-section img-is-responsive">
<?php if ( has_post_thumbnail() ) : ?>
<?php the_post_thumbnail('small-block-thumb'); ?>
<?php endif; ?>
</div>
<div class="squiggle-post-meta-section clearfix">
<h2> <?php the_title(); ?> </h2>
<div class="excerpt-post"><?php the_excerpt(); ?></div>
</div>
<div class="continue-reading-section">
Continue reading <i class="fa fa-chevron-right"></i>
</div>
<div class="squiggly-line"></div>
</div>
<?php
the_posts_pagination( array(
'mid_size' => 2,
'prev_text' => esc_html( '←' ),
'next_text' => esc_html( '→' ),
) );
?>
<?php wp_reset_query(); // reset the query ?>
In order to do that there are a few steps you need to do, first of all i suggest you use the wp-pagenavi plugin, it handles lots of things for you.
Any way, i explain both ways, with and without the plugin,
first we write our query and set the paged attribute according to paged query var, so when the user navigates to for example page 3, the query filters posts and shows the third page posts:
$paged = (int) ( get_query_var( 'paged' ) ?: ( get_query_var( 'page' )?: 1 ) );
$my_query = new WP_Query( array(
'posts_per_page' => 10,
'paged' => $paged // This is important for pagination links to work
) );
Now if you have decided to use the wp-pagenavi plugin, it's quite easy to make paginations with custom queries, all you need to do is :
<?php if( function_exists('wp_pagenavi') ) wp_pagenavi( array( 'query' => $my_query ) ); ?>
But if you wish to use the_posts_pagination() function, i'm not sure if it supports custom queries, but since it's using the paginate_links() function , it should work with this arguments
$args = array(
'current' => max( 1, $paged ), // $paged is what we defined earlier or you can use just get_query_var('paged')
'total' => $my_query->max_num_pages
)
if it doesn't, you can use the paginate_links() function itself with the same above arguments.
See also : this answer
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
query_posts(array('post_type' => 'post', 'order' => 'ASC', 'paged' => $paged, 'posts_per_page' => 12 ));
if( have_posts() ) : ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php the_title();?>
<?php the_excerpt(); ?>
<?php endwhile; ?>
<div class="pagination"><?php my_pagination(); ?></div>
<?php endif; ?>
<?php wp_reset_query(); ?>
In your functions.php add,
if ( ! function_exists( 'my_pagination' ) ) :
function my_pagination() {
global $wp_query;
$big = 999999999; // need an unlikely integer
echo 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
) );
}
endif;
OR
Try this: http://www.wpbeginner.com/wp-themes/how-to-add-numeric-pagination-in-your-wordpress-theme/
Related
Scenario
I'm trying to understand where I have gone wrong with my loop in regards to using my pagination hook. I'm using the theme Understrap, with Understrap-child, and i've made no edits to the pre-built hook which can be found here.
I've used this hook in the loop listed below, which resides in a page template file. However the pagination hook isn't being output? The rest of the loop however, working perfectly fine.
Here's the kicker, I've used exactly the same structure within my index.php file. and it works completely fine. Which is driving me to believe I may need to declare something, just not sure as to what that may be.
Question
I'm wondering if while using a page template, and new WP_Query(); would I need to declare any globals to get $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; to work?
Code in Question
For reference I've included my loop, though I'm pretty sure it's ok.
<div class="bg-light">
<div class="container space-top-3 space-bottom-2">
<div class="row">
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => 'post',
'orderby' => 'post_date',
'order' => 'desc',
'perm' => 'readable',
'show_post_views' => true,
'posts_per_page' => 9,
'paged' => $paged
);
$latestArticles = new WP_Query( $args );
if( $latestArticles->have_posts() ):
/* Start the Loop */
while( $latestArticles->have_posts() ) : $latestArticles->the_post();
get_template_part( 'loop-templates/content-search', get_post_format() );
endwhile;
endif;?>
</div>
<div class="row mt-3">
<div class="col-auto">
<!-- The pagination component (currently not being output. not sure why.) -->
<?php understrap_pagination(); ?>
</div>
</div>
<?php wp_reset_query(); ?>
<?php else : ?>
<!-- do nothing -->
<?php endif; ?>
</div>
</div>
Thanks for all help, in advance.
Edit-7/11/19:
Tried passing $latestArticles->max_num_pages to understrap_pagination();as such understrap_pagination($latestArticles->max_num_pages);. - Still no luck. :|
The pagination function relies upon $wp_query->max_num_pages (i.e. the max number of pages for the main query), so the function will not work with custom queries:
function understrap_pagination( $args = array(), $class = 'pagination' ) {
if ( $GLOBALS['wp_query']->max_num_pages <= 1 ) {
return;
}
...
}
And while your approach does work, it's really not a good idea to alter the global $wp_query object because doing so is essentially the same as using query_posts() which is not recommended at all — you can see why so by checking the docs here.
However, if you don't want to edit the pagination function (or create your own), then a less risky workaround to get the pagination works with your custom query, is by temporarily changing the — and only the — $wp_query->max_num_pages:
$orig_max_num_pages = $wp_query->max_num_pages; // backup
// Change it just for the pagination.
// and $latestArticles is your custom WP_Query instance.
$wp_query->max_num_pages = $latestArticles->max_num_pages;
$paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
understrap_pagination( [
'current' => $paged,
] );
$wp_query->max_num_pages = $orig_max_num_pages; // restore
Sample Page template based on your original code.
A Better Practice: Copy/Edit the pagination function.
Since you're using a child theme, and that Understrap uses locate_template() to load the file (inc/pagination.php) which defines the pagination function, you can just copy the file to the child theme (your-theme/inc/pagination.php) and edit the function so that it works with custom WP_Query queries. Or since the function is pluggable (i.e. defined with a if ( ! function_exists() ) block), you can just copy the code to your child theme's functions.php file.
You can use this modified function (which works well for me) or use it as a reference to create your own:
function understrap_pagination( $args = array(), $class = 'pagination' ) {
$args = wp_parse_args(
$args,
array(
'mid_size' => 2,
'prev_next' => true,
'prev_text' => __( '«', 'understrap' ),
'next_text' => __( '»', 'understrap' ),
'screen_reader_text' => __( 'Posts navigation', 'understrap' ),
'type' => 'array',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $GLOBALS['wp_query']->max_num_pages,
)
);
// Nothing to paginate, so let's bail.
if ( ! $links = paginate_links( $args ) ) {
return;
}
?>
<nav aria-label="<?php echo $args['screen_reader_text']; ?>">
<ul class="pagination">
<?php
foreach ( $links as $key => $link ) {
?>
<li class="page-item <?php echo strpos( $link, 'current' ) ? 'active' : ''; ?>">
<?php echo str_replace( 'page-numbers', 'page-link', $link ); ?>
</li>
<?php
}
?>
</ul>
</nav>
<?php
}
Then in your template, call the function like so:
$paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
understrap_pagination( [
'current' => $paged,
'total' => $latestArticles->max_num_pages,
] );
Sample Page template based on your original code.
paged vs page
paged and page are both the number of the current page, however:
paged is used with archive-based requests/URLs such as category archives and search results pages. On these requests, page is not set by default. It should also be noted that paged is used with is_paged().
page is used with singular requests/URLs such as single Post and Page pages. On these requests, paged is not set by default.
And the Codex recommends the following approach to get the proper page number on singular requests/URLs:
if ( get_query_var( 'paged' ) ) { $paged = get_query_var( 'paged' ); }
elseif ( get_query_var( 'page' ) ) { $paged = get_query_var( 'page' ); }
else { $paged = 1; }
Or simpler version: $paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
NB: That Codex article refers to static front Page, but the information also applies to any Pages/Posts.
And last but not least… with secondary WP_Query calls (like your $latestArticles = new WP_Query( $args )), you just need to call wp_reset_postdata() and no need to call wp_reset_query(). :)
So, I was able to locate this post here by CSS-Tricks which outlines a method that nukes the current $wp_query variable and replaces it with a new instance of WP_Query();
My loop now works as expected however, I was under the impression that $wp_query is reserved, is that not correct? Is it safe to use this method?
My new loop looks like this;
<div class="bg-light">
<div class="container space-top-3 space-bottom-2">
<div class="row">
<?php
$temp = $wp_query;
$wp_query = null;
$wp_query = new WP_Query();
$args = array(
'post_type' => 'post',
'orderby' => 'post_date',
'order' => 'desc',
'perm' => 'readable',
'show_post_views' => true,
'posts_per_page' => $posts_per_page,
'paged' => $paged
); ?>
<?php $wp_query->query($args); ?>
<?php if ( $wp_query->have_posts() ) : ?>
<?php /* Start the Loop */ ?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<?php get_template_part( 'loop-templates/content-search', get_post_format() ); ?>
<?php endwhile; ?>
</div>
<div class="row mt-3">
<div class="col-auto">
<!-- The pagination component -->
<?php understrap_pagination(); ?>
</div>
</div>
<?php else : ?>
<!-- do nothing -->
<?php endif; ?>
<?php $wp_query = null;
$wp_query = $temp; // Reset ?>
</div>
</div>
If anyone knows of a better approach I'd be interested in hearing it. Many thanks in advance. -B.
I am trying to build a paginated archive sidebar using WP_Query. As the same sidebar is used on both single.php and news.php, the arguments used for the WP_Query are different.
On news.php, the pagination works perfectly, but on single.php the pagination links are present, and have the correct href values, but simply reload the page when clicked, i.e. anything beyond page 1 is inaccessible.
Update: Just in case this is relevant, single.php makes use of the Share Buttons by AddToAny, and Social (by MailChimp) plugins. I have deactivated both, but this has not fixed the issue with pagination.
Can anyone shed some light on this for me? Code here:
<aside>
<header>
<h1 class="column-title">Archive</h1>
<hr>
</header>
<div>
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
// remove first four posts if this is the news main page
if ( ! is_single() ) {
// Save first four posts
$first_four = new WP_Query ('post_type=post&orderby=date&order=desc&posts_per_page=4');
if ( $first_four->have_posts() ) : while ( $first_four->have_posts() ) : $first_four->the_post();
$skipIDs[] = $post->ID;
endwhile; endif;
wp_reset_postdata();
// Save all posts
$args = array(
'post_type' => 'post',
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => -1
);
$all_posts = new WP_Query($args);
while ( $all_posts->have_posts() ) : $all_posts->the_post();
// Skip first four posts and save rest
if ( in_array($post->ID,$skipIDs) ) { continue; };
$offset_array[] = $post->ID;
endwhile;
wp_reset_postdata();
// Final arguments for WP_Query
$args = array(
'post__in' => $offset_array,
'paged' => $paged,
'posts_per_page' => 5
);
} else {
// Args for single.php
$args = array(
'post_type' => 'post',
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => 5,
'paged' => $paged
);
}
$article_archive = new WP_Query($args);
$max_pages = $article_archive->max_num_pages;
if( $article_archive->have_posts() ) : while( $article_archive->have_posts() ) : $article_archive->the_post();
$has_image = get_the_post_thumbnail($post->ID,'thumbnail'); ?>
<article class="group">
<a class="anchor-overlay" href="<?php the_permalink(); ?>"></a>
<?php if( $has_image ) { echo $has_image; } else { echo "<img src='/wp-content/themes/DCSFC/images/news-calendar/news/no-image.jpg' alt='No image' />"; } ?>
<div>
<h3><?php the_title(); ?></h3>
<time datetime="dd/MM/YYYY"><?php echo get_the_date(); ?></time>
</div>
</article>
<?php endwhile; endif;
wp_reset_postdata();
$big = 999999999; // need an unlikely integer
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $max_pages
) );
?>
</div>
I have a static frontpage on my wordpress website, displaying my posts. Currently it shows 10 posts and I want to make it possible to click "next page" to see the next 10 posts in the query and so on. I have tried getting the pagination to work, but it looks like I'm unable to connect it with my search query.
Here is my query:
<?php
query_posts(
array( 'post_type' => 'post',
'order' => 'DESC',
'meta_key' => 'cf_votes',
'orderby' => 'meta_value_num',
'posts_per_page' => 10
)
);
?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_query(); ?>
And here is the pagination I have tried:
<?php
global $wp_query;
$big = 999999999;
echo 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
) );
?>
So basically I'm able to see the first 10 posts perfectly. But no alternative to see more posts is shown.
Wordpress Codex is pretty comprehensive on the Pagination problem, I recommend you to see this:
http://codex.wordpress.org/Pagination#Adding_the_.22paged.22_parameter_to_a_query
There's a section specifically for the Static Front Page.
Something like:
<?php
if ( get_query_var('paged') ) { $paged = get_query_var('paged'); }
elseif ( get_query_var('page') ) { $paged = get_query_var('page'); }
else { $paged = 1; }
$args = array(
'posts_per_page' => 3,
'paged' => $paged
);
query_posts($args);
?>
<?php if ( have_posts() ) : ?>
<!-- Add the pagination functions here. -->
<!-- Start of the main loop. -->
<?php while ( have_posts() ) : the_post(); ?>
<!-- the rest of your theme's main loop -->
<?php endwhile; ?>
<!-- End of the main loop -->
<!-- Add the pagination functions here. -->
<div class="nav-previous alignleft"><?php next_posts_link( 'Older posts' ); ?></div>
<div class="nav-next alignright"><?php previous_posts_link( 'Newer posts' ); ?></div>
<?php else : ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
I am facing a little issue while adding pagination to a custom post type which I've created inside Wordpress. The pagination links are appearing on the template where I've all the posts, inside the custom post type, listed but when I click on the link to view Older posts, it opens the second page but the same posts from the first page are displayed there. Moreover, on the second page, the 'Older posts' link doesn't update to '../page/3', instead it stays '../page/2'. I followed the steps specified here (https://stackoverflow.com/a/18325002/2115001) and modified my code according to the information listed under 'Option 2'. Here's what my code currently looks like:
<?php
$temp = $wp_query;
$wp_query = null;
$wp_query = new WP_Query();
$wp_query->query('showposts=3&post_type=medals'.'&paged='.$paged);
while ($wp_query->have_posts()) : $wp_query->the_post();
// loops code here
endwhile;
echo '<nav>';
echo previous_posts_link('« Newer');
echo next_posts_link('Older »');
echo '</nav>';
$wp_query = null;
$wp_query = $temp; // Reset
?>
Do I need to add some code to the functions.php file in order for this to function properly or there's something wrong in my original code? Thanks.
Try below code
$paged = get_query_var('page') ? get_query_var('page') : 1;
$args = array('posts_per_page' => 3,
'paged'=> $paged,
'post_type' => 'medals');
$wp_query = new WP_Query($args);
while ($wp_query->have_posts()) : $wp_query->the_post();
// loops code here
endwhile;
global $wp_query;
$big = 999999999;
echo 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,
'next_text' => __('Next »'),
));
Try this:
<?php
$type = 'portfolio';
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'post_type' => $type,
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => 1,
'caller_get_posts'=> 1
);
$temp = $wp_query; // assign original query to temp variable for later use
$wp_query = null;
$wp_query = new WP_Query();
wp_query->query($args);
?>
then put your permalinks to the default structure and back to how the structure was.
<?php while ( $query->have_posts() ) : $query->the_post(); ?>
<article class="">
<div class="">
<h4><?php the_time( 'm' ); ?></h4>
<h4><?php the_time( 'd' ); ?></h4>
</div>
<div class="">
<h5><?php the_title(); ?></h5>
<p><?php the_excerpt(); ?></p>
</div>
</div>
</a>
</article>
<?php endwhile; // End the loop. Whew. ?>
<?php
global $wp_query;
$big = 999999999; // need an unlikely integer
//echo esc_url( get_pagenum_link());
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $query->max_num_pages,
'type'=>'list',
'prev_text' => __('<'),
'next_text' => __('>'),
) );
?>
Hope it will work for you.
Can a Wordpress expert confirm - is there a simple, elegant, Wordpress-native way in which get_posts() queries can be paginated? I have tried to piece together how to do it from various posts, but can't seem to get it to work.
I often use get_posts() for querying my Custom Post types - but if I can't easily paginate these I may just drop get_posts() and get into the habit of using wp_query() for Custom POst Types.
What is wrong with my code? I have struggled through many PHP problems, but would still consider myself a novice.
Trying for the simplest clearest option here so I can understand how it works, use it as a template for future projects.
<div class="content-primary">
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$query_args = array(
'post_type' => 'project',
'posts_per_page' => 10,
'paged' => $paged
);
$query_custom_posts = get_posts( $query_args );
foreach ( $query_custom_posts as $post ) : setup_postdata( $post ); ?>
<article>
<a href="<?php the_permalink(); ?>">
<?php if ( has_post_thumbnail() ) : the_post_thumbnail( 'thumbnail' ); endif;?>
<h3><?php the_title(); ?></h3>
</a>
<div><?php the_date(); ?></div>
<div><?php the_excerpt(); ?></div>
</article>
<?php endforeach; ?>
<?php
global $query_args;
$big = 999999999; // need an unlikely integer
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $query_args->max_num_pages
) );
?>
<?php wp_reset_postdata();?>
</div>
I really hoped this would work, though I am aware of errors in it - I know my $query_args contains no max_num_pages.
Would be nice to have the optional use of the Wordpress next_posts_link() / previous_posts_link() too, rather than paginate_links(), but not sure if this can be made to work with get_posts().
You simply need to add the following line:
<?php query_posts('post_type=post&paged='. get_query_var('paged')); ?>
just before your get_posts() loop starts.
Full article here: http://blog.onireon.it/wordpress-get_posts-and-pagination-posts-are-correctly-displayed-but-no-pagination-links-are-showing/