I am having trouble with Wordpress pagination. I have a custom archive page displaying custom post types from the specific category. I want to use pagination and display 12 posts per page. My problem is that pagination works correctly but only up to the 8th page. After that I am being presented with "Page not found".
I am using theme built-in function to display page navigation (1, 2... 10, 11). It correctly shows 11 pages in total, but they seem not to work after the 8th page.
$taxonomy = 'product_cat';
$term_id = get_queried_object()->term_id;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'product',
'paged' => $paged,
'posts_per_page' => '12',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $term_id
)
)
);
<?php $wp_query = new WP_query( $args ); ?>
<?php if( $wp_query->have_posts() ): ?>
<?php while( $wp_query->have_posts() ): ?>
<?php $wp_query->the_post(); ?>
//post content
<?php endwhile; ?>
<?php endif; ?>
<?php s7upf_paging_nav();?>
<?php wp_reset_postdata(); ?>
#edit
When I go to a different category page which should have 12 pages they work correctly up to the 9th page.
If I go to the one that has 2 pages, only the first one works.
I tried updaing permalinks. Setting posts per page to 12 in wordpress settings.
When i change posts per page in my query args to -1 it correctly shows all the posts on one page.
When manually setting the number of a page to display ('paged' => '11') it also displays correct page with correct posts.
You are using the wrong query. On page you are creating your own query instead of the actual query the page already did.
This will also be better for performance.
Step 1. Check what is in the normal query.
At the top of taxonomy-product_cat.php
global $wp_query;
var_dump( $wp_query->query_vars );
That probably fits mostly.
Step 2. Do the normal loop
Remove all your query stuff (maybe keep a backup of the $args for the next step)
example: Replace
<?php if( $wp_query->have_posts() ): ?>
with
<?php if( have_posts() ): ?>
And so on.
Step 3. Edit the main query
We are going to use the hook pre_get_posts
add_action('pre_get_posts', 'so_53315648');
function so_53315648( WP_Query $wp_query ){
// only check this on the main query
if (! $wp_query->is_main_query() ){
return;
}
// only check this on the product_cat taxonomy
if ( ! $wp_query->is_tax('product_cat')) {
return;
}
// maybe do some more checks?
$wp_query->query_vars['posts_per_page'] = 12;
// Is this really needed??
//$wp_query->query_vars['posts_type'] = 'product';
// tweak the query the way you like.
}
As you can see $wp_query->query_vars should pretty much be the same $args. But do not overwrite it. This might break other stuff.
Of course I could not test your specific site. But the answer should be inside the pre_get_posts hook. And tweaking the main query instead of doing a extra separate one.
Test, also check the var_dump of step 1 that your changes are coming through.
The checks at the top are to stop other pages from being affected, maybe you need more?
Let me know.
Related
I made a "load more" button to my website, following this awesome tutorial.
Everything works fine, but in the homepage i have 3 different loops (1 sticky post, 3 evidence) and the load more starts from post #5.
In the main loops, I have excluded the already-showed posts with the IDs and "post__not_in" and everything works fine.
The problem is when I call the load more, the loop starts from post 1. If I set to start from page 2 I have a duplicate post (that's because I have to load post in multiple of 3).
I'have tried to get the IDs list in my loadmore file with GLOBALS, but it seems not working :(
How can I pass my main loop variable to the load more query?
This is my main loop:
<?php
$myquery = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 3,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'post__not_in' => $ids
]); if($myquery->have_posts()): ?>
<div class="articles-container append-posts">
<?php
while($myquery->have_posts()) : $myquery->the_post();
$ids[] = get_the_ID(); ?>
<?php get_template_part( 'template-parts/loop', 'posts' ); ?>
<?php endwhile; ?>
</div>
This is the load-more file:
function misha_loadmore_ajax_handler(){
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
$args['post_type'] = 'post';
$args['post_per_page'] = 3;
$args['orderby'] = 'date';
$args['order'] = 'DESC';
// it is always better to use WP_Query but not here
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/loop', 'posts' );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; // here we exit the script and even no wp_reset_query() required! }
I am trying to use a custom WP_Query for my loop in order to limit the number of posts that I show per page. However, the pagination functions doesn't seem to respect this limit that I set. Here is my code:
$current_page = (get_query_var('paged')) ? get_query_var('paged') : 1;
$author_post_args = array(
'post_type' => 'post',
'author_name' => $curauth->user_nicename,
'posts_per_page' => 5,
'paged' => $current_page,
'orderby' => 'modified',
'no_found_rows' => true,
'ignore_sticky_posts' => '1'
);
$loop = new WP_Query( $author_post_args );
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $loop;
if($loop->have_posts()):
while($loop->have_posts()): $loop->the_post(); ?>
<div class="post-list">
<?php
$title = the_title("", "", false);
?>
<h2><?php echo $title; ?></h2>
<time>Last Updated — <?php the_modified_date('F j, Y'); ?></time>
<p><?php the_excerpt(); ?></p>
</div>
<?php
endwhile;
endif;
wp_reset_postdata();
previous_posts_link('<i class="fas fa-backward"></i> Newer Posts');
next_posts_link('Older Posts <i class="fas fa-forward"></i>', $loop->max_num_pages);
$wp_query = NULL;
$wp_query = $temp_query;
I searched for a solution on the website and found this question. The solution seems to work for the OP but not for me.
In my case, the posts per page are limited to 5. However, the number of pages is still stuck at 3. I can't go to page 4 and get a Not Found error. There are total 26 posts by the author. Therefore, I should be able to go to page 6.
The number of pages is still determined by the functions based on the value specified under Settings > Reading > Blog pages show at most in WordPress dashboard which is set to 10.
What am I doing wrong?
Thanks.
The problem is that WordPress is working off of the assumption that you're still expecting 10 posts per page because your query is effectively a standalone query in the middle of a page. Are you just trying to limit the number of posts per page on this particular post type? Or is there something else you're trying to do?
You can achieve this in a far cleaner way by using pre_get_posts
function tweak_posts_per_page( $query ) {
if( !is_admin() && $query->is_author() && $query->is_main_query() ) :
$query->set( 'posts_per_page', 5 );
$query->set( 'orderby', 'modified' );
return;
endif;
}
add_action('pre_get_posts', 'tweak_posts_per_page');
Add this code in your functions.php file or similar; if needed you can add additional conditionals to the IF statement to handle when this adjustment will be applied. You should find your pagination will work after that.
pre_get_posts is used to adjust the query that WordPress will run before it runs the query
Additionally, you can remove the query from your code altogether - just keep the loop in there to loop through what is now your adjusted main query.
edit: added the additional 'is_author' conditional statement, and added the 'orderby' adjustment
The problem I'm facing is that on one Page my pagination urls always redirect to the homepage. The urls behind the pagination buttons look correct ( domein.com/currentpage/page/2 ) but it always redirects. The template is a copy of a page where it works perfectly, with only the post type changed to fit the content of this page. The pagination is rendered correctly, so the number of pages and items on it are correct. Both use the same custom pagination. The same pagination works on multiple pages in my site, except this one
So this one works:
https://www.startpuntonderwijs.nl/vacatures/
And this one doesn't
https://www.startpuntonderwijs.nl/leveranciers/
I've compared both scripts extensively and they seem 100% equal except for the lack of filters in "leveranciers" which I don't need there, and the different post type used in the query.
Both links normal pages with their own template. Both have their own taxonomie's and posts with a matching post type.
<?php
// Set counter to 0
$counter = 0;
// paged variable
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
// find ID's of all posts with the needed post type
$query_items = get_posts(array('post_type' => 'leveranciers',
'post_status'=>'publish', 'posts_per_page'=>-1));
//create a new variable with the post ids
foreach( $query_items as $item ) {
$allposts[]=$item->ID;
}
// the query
$wpb_all_query = new WP_Query(
array(
'post_type' => 'leveranciers',
'post__in' => $allposts,
'paged' => $paged,
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => 10)
);
if ( $wpb_all_query->have_posts() ) : ?>
<ul>
<!-- the loop -->
<?php while ( $wpb_all_query->have_posts() ) : $wpb_all_query->the_post(); ?>
<!-- Presenting the info from the posts -->
<?php endwhile;
if (function_exists('custom_pagination')) {
custom_pagination($wpb_all_query->max_num_pages,"",$paged);
} ?>
Expected result would be that
https://www.startpuntonderwijs.nl/leveranciers/page/2/
would result the second page of paginated results for "leveranciers"
But instead it always redirects to the homepage. and the "/page/2/" drops out of the url.
I have a custom Wordpress widget which allows the user to filter products via attributes (custom taxonomies).
It all happens via an Ajax call, but I'm having trouble keeping the pagination up to date based on the filtered results.
For example:
If the page loads 30 products, 10 to a page = 3 pages of results.
The user then filters by an attribute which reduces that 30 products to 20. I need the pagination to change to just 2 pages of results.
Here's a sample of the WP_Query that replaces the default page content. You can see the woocommerce_pagination() which doesn't appear to work in this environment.
// Args
$args = array(
'post_type' => 'product',
'posts_per_page' => 10,
'orderby' => 'name',
'order' => 'ASC',
'tax_query' => $tax_query
);
$query = new WP_Query( $args );
if( $query->have_posts() ) :
woocommerce_product_loop_start();
while( $query->have_posts() ): $query->the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
woocommerce_product_loop_end();
// TODO - get pagination working
woocommerce_pagination();
wp_reset_postdata();
else :
echo '<p>No products found</p>';
endif;
WooCommerce pagination works based on global $wp_query variable. But you are using your own $query variable. That's why it is obvious why it is not working.
You have 2 ways to go:
First is using query_posts instead of WP_QUERY class.
The second way is a small hack, where you can cheat $wp_query pagination argument.
Here it is:
global $wp_query;
$wp_query->max_num_pages=$query->max_num_pages;
// TODO - get pagination working
woocommerce_pagination();
i have a custom post type and would like to change the number of posts per page. i use the following code to show/limit the posts:
$args = array(
'post_type' => 'movie',
'posts_per_page' => 3,
'tax_query' => array(
array(
'taxonomy' => $wp_query->queried_object->taxonomy,
'field' => 'slug',
'terms' => $wp_query->queried_object->slug,
)
),
'paged' => get_query_var('paged') ? get_query_var('paged') : 1
);
query_posts( $args );
for this time i have 20 posts with this post type and the default posts per page in wordpress admin (settings/read ...) is set to 10.
if i call the url without a page it shows 3 posts, if i call the url with "page/2/" it shows 3 posts but if i call the page with "page/3/" it shows nothing found ...
i wouldn't change the default value for the posts in the admin - does someone have a idea?
note: to "debug" i let me show the value for "$wp_query->post_count;" - this use the default admin posts per page - 10 ...
regards kai
When you load the page, it will do a query before the template file (archive.php) is called.
That first query will use the defaults set in WordPress; ie. 10 posts per page. By the sounds of things, you're running that second 'query_posts' call within archive.php, but it sounds like that is after you have run the appropriate checks.
Two possible solutions for you:
Modify the first query with the posts_per_page
add_filter( 'pre_get_posts', 'modify_movie_query' );
function modify_movie_query( $wp_query ) {
if( $wp_query->query_vars['post_type'] != 'movie' ) return;
$wp_query->query_vars['posts_per_page'] = 3;
}
Because you have modified a reference to $wp_query, you don't need to return it.
Run the query_posts call at the top of the archive.php template
Option 1 is what I would recommend - it's the most efficient, and the most appropriate.
The approved answer doesn't really work if the archive page is for a custom taxonomy. In that case, you might want to use the following:
add_filter( 'pre_get_posts', 'modify_movie_query' );
function modify_movie_query( $wp_query ) {
if(is_tax('movie-category')){
$wp_query->query_vars['posts_per_page'] = 10;
}
return $wp_query
}