admin管理员组文章数量:1287879
I am having trouble getting pagination working for custom taxonomy archive with the custom query. The pagination on the taxonomy archive ends up with a 404 page.
I have to run a query multiple times on many areas, so I have created a method for that.
Query Method
/**
* @param bool $post_type
* @param bool $posts_per_page
* @param bool $paged
* @param array $extra_args
*
* @return \WP_Query
*/
public function module_query( $post_type = FALSE, $posts_per_page = FALSE, $paged = FALSE, array $extra_args = [] ) {
// basic arguments
$args = [
'post_type' => $post_type ? $post_type : self::get_module_cpt(),
'posts_per_page' => $posts_per_page ? $posts_per_page : - 1,
'orderby' => 'title',
'order' => 'ASC',
];
// set paged
if ( $paged ) {
$args[ 'paged' ] = $paged;
}
$args = wp_parse_args( $extra_args, $args );
// init meta query var
$meta_query = [];
$meta_query[] = [
'relation' => 'AND',
[
'key' => 'permit_roles',
'compare' => 'NOT EXISTS',
],
[
'key' => 'permit_users',
'compare' => 'NOT EXISTS',
],
];
$meta_query[] = [
'relation' => 'AND',
[
'key' => 'permit_roles',
'value' => '',
'compare' => '=',
],
[
'key' => 'permit_users',
'value' => '',
'compare' => '=',
],
];
// init permit roles var
$permit_roles = [];
$r = 0;
// loop through each roles and prepare array for meta query
foreach ( $this->get_current_user_roles() as $current_user_role ) {
$permit_roles[ $r ][ 'key' ] = 'permit_roles';
$permit_roles[ $r ][ 'value' ] = sprintf( ':"%s";', $current_user_role );
$permit_roles[ $r ][ 'compare' ] = 'LIKE';
$r ++;
}
$meta_query[] = [
'relation' => 'OR',
$permit_roles,
[
'key' => 'permit_users',
'value' => sprintf( ':"%s";', get_current_user_id() ),
'compare' => 'LIKE',
],
];
// add meta query relation if more than one query
if ( count( $meta_query ) > 1 ) {
$meta_query[ 'relation' ] = 'OR';
}
// add meta query only for non admin users
if ( ! current_user_can( 'administrator' ) ) {
$args[ 'meta_query' ] = $meta_query;
}
// return the query object
return new WP_Query( $args );
}
taxonomy.php Query
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$the_query = $cp->module_query(
$cp::get_resource_cpt(), cp_get_addons_per_page(), $paged,
[
'orderby' => 'publish_date',
'tax_query' => [
'taxonomy' => $term->taxonomy,
'field' => 'slug',
'terms' => [ $term->slug ],
'operator' => 'IN',
],
]
);
...
// while loop
...
// pagination
$cp->bootstrap_pagination( $the_query );
// reset query
wp_reset_postdata();
Pagination function
The pagination is working fine on the Custom Post time page with a custom loop.
function bootstrap_pagination( \WP_Query $wp_query = NULL, $echo = TRUE ) {
if ( NULL === $wp_query ) {
global $wp_query;
}
$pages = paginate_links( [
'base' => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'type' => 'array',
'show_all' => FALSE,
'end_size' => 3,
'mid_size' => 1,
'prev_next' => TRUE,
'prev_text' => __( '« Prev' ),
'next_text' => __( 'Next »' ),
'add_args' => FALSE,
'add_fragment' => '',
]
);
if ( is_array( $pages ) ) {
$pagination = '<div class="row"><div class="col mt-5"><div class="pagination d-flex justify-content-center"><ul class="pagination pagination-sm">';
foreach ( $pages as $page ) {
$pagination .= '<li class="page-item' . ( strpos( $page, 'current' ) !== FALSE ? ' active' : '' ) . '"> ' . str_replace( 'page-numbers', 'page-link', $page ) . '</li>';
}
$pagination .= '</ul></div></div></div><!-- end pagination -->';
if ( $echo ) {
echo $pagination;
} else {
return $pagination;
}
}
return NULL;
}
I am having trouble getting pagination working for custom taxonomy archive with the custom query. The pagination on the taxonomy archive ends up with a 404 page.
I have to run a query multiple times on many areas, so I have created a method for that.
Query Method
/**
* @param bool $post_type
* @param bool $posts_per_page
* @param bool $paged
* @param array $extra_args
*
* @return \WP_Query
*/
public function module_query( $post_type = FALSE, $posts_per_page = FALSE, $paged = FALSE, array $extra_args = [] ) {
// basic arguments
$args = [
'post_type' => $post_type ? $post_type : self::get_module_cpt(),
'posts_per_page' => $posts_per_page ? $posts_per_page : - 1,
'orderby' => 'title',
'order' => 'ASC',
];
// set paged
if ( $paged ) {
$args[ 'paged' ] = $paged;
}
$args = wp_parse_args( $extra_args, $args );
// init meta query var
$meta_query = [];
$meta_query[] = [
'relation' => 'AND',
[
'key' => 'permit_roles',
'compare' => 'NOT EXISTS',
],
[
'key' => 'permit_users',
'compare' => 'NOT EXISTS',
],
];
$meta_query[] = [
'relation' => 'AND',
[
'key' => 'permit_roles',
'value' => '',
'compare' => '=',
],
[
'key' => 'permit_users',
'value' => '',
'compare' => '=',
],
];
// init permit roles var
$permit_roles = [];
$r = 0;
// loop through each roles and prepare array for meta query
foreach ( $this->get_current_user_roles() as $current_user_role ) {
$permit_roles[ $r ][ 'key' ] = 'permit_roles';
$permit_roles[ $r ][ 'value' ] = sprintf( ':"%s";', $current_user_role );
$permit_roles[ $r ][ 'compare' ] = 'LIKE';
$r ++;
}
$meta_query[] = [
'relation' => 'OR',
$permit_roles,
[
'key' => 'permit_users',
'value' => sprintf( ':"%s";', get_current_user_id() ),
'compare' => 'LIKE',
],
];
// add meta query relation if more than one query
if ( count( $meta_query ) > 1 ) {
$meta_query[ 'relation' ] = 'OR';
}
// add meta query only for non admin users
if ( ! current_user_can( 'administrator' ) ) {
$args[ 'meta_query' ] = $meta_query;
}
// return the query object
return new WP_Query( $args );
}
taxonomy.php Query
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$the_query = $cp->module_query(
$cp::get_resource_cpt(), cp_get_addons_per_page(), $paged,
[
'orderby' => 'publish_date',
'tax_query' => [
'taxonomy' => $term->taxonomy,
'field' => 'slug',
'terms' => [ $term->slug ],
'operator' => 'IN',
],
]
);
...
// while loop
...
// pagination
$cp->bootstrap_pagination( $the_query );
// reset query
wp_reset_postdata();
Pagination function
The pagination is working fine on the Custom Post time page with a custom loop.
function bootstrap_pagination( \WP_Query $wp_query = NULL, $echo = TRUE ) {
if ( NULL === $wp_query ) {
global $wp_query;
}
$pages = paginate_links( [
'base' => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'type' => 'array',
'show_all' => FALSE,
'end_size' => 3,
'mid_size' => 1,
'prev_next' => TRUE,
'prev_text' => __( '« Prev' ),
'next_text' => __( 'Next »' ),
'add_args' => FALSE,
'add_fragment' => '',
]
);
if ( is_array( $pages ) ) {
$pagination = '<div class="row"><div class="col mt-5"><div class="pagination d-flex justify-content-center"><ul class="pagination pagination-sm">';
foreach ( $pages as $page ) {
$pagination .= '<li class="page-item' . ( strpos( $page, 'current' ) !== FALSE ? ' active' : '' ) . '"> ' . str_replace( 'page-numbers', 'page-link', $page ) . '</li>';
}
$pagination .= '</ul></div></div></div><!-- end pagination -->';
if ( $echo ) {
echo $pagination;
} else {
return $pagination;
}
}
return NULL;
}
Share
Improve this question
asked Jul 6, 2020 at 6:54
pixelngrainpixelngrain
1,3901 gold badge23 silver badges50 bronze badges
3
|
2 Answers
Reset to default 2In short, your code is fine, but the custom query's pagination and the one for the main query, they can't be using the same paged
URL query string (which WordPress reads the value from for the paged
query arg used in a WP_Query
request).
Why the error 404?
So for examples, paginated/paged category requests can have one of these URLs:
Full pretty URL:
https://example/category/uncategorized/page/2/
Semi-pretty URL which redirects to the above URL:
https://example/category/uncategorized/?paged=2
"Ugly URL" (e.g. when permalinks are not enabled)
https://example/?cat=1&paged=2
And as you can see, the URLs are using the query string paged
which you can get the value using get_query_var( 'paged' )
. (Note that in the first URL, the page/2
is equivalent to paged=2
)
And because a category/taxonomy archive is a non-singular request (just like search results pages), the paged
value will be used in the main query's request, i.e. the SQL command for querying the requested archive, unless of course if pagination is not enabled for the main query.
Therefore, the paged
value needs to be valid, i.e. it must not exceed the max number of pages for that specific request (the main query). And if the max is exceeded, then you'd get a 404
error because there were no more posts found via the main query. Just like a book with 10 pages (including covers); there's logically no page #11, right?
So because your custom query is being paginated using the paged
query string, then if you get the error 404, it's likely because the custom query had more pages than the main query.
Sample scenario demonstrating the above:
On a category archive page (e.g. at
example/category/uncategorized
), there were 3 pages shown in the pagination. And that's for the main query which WordPress runs first on page load.Then in the category template, you run a custom query for, maybe a custom post type.
Then you added a pagination for the custom query and there were 5 pages shown in that pagination.
So if both the paginations are using the same
paged
query string, then for example, going to page #4 will cause a404
error because the main query (for the category) had only at most 3 pages of results.
How to fix the error
(Note: These are listed in no specific order.)
As I said in the comments, you can use a custom URL query string like
page_num
,pg
, etc. along withpaged
.So the
paged
will always be just for the main query, whilepage_num
orpg
will be used with your custom query.Use AJAX instead to paginate the custom query, but AJAX is not in scope of this answer. (Or that it's up to you to look for a solution and implement it.)
Use a static Page (post of the
page
type), e.g. atexample/my-tax-archive
, and run your custom queries in the Page Template.For singular requests, WordPress doesn't use the
paged
in the request SQL, so thepaged
value can be any number (2, 20, 200, 2000, etc.).
But there's a trick to make paged
works for both the main query and custom queries.. on archive pages.
Add this to your theme's
functions.php
file:add_action( 'pre_get_posts', function ( $query ) { if ( is_admin() || ! $query->is_main_query() || ! is_tax( 'your_tax' ) ) { return; } if ( ! empty( $_GET['pgs'] ) && ( $paged = max( 1, $query->get( 'paged' ) ) ) && // Runs only if the current page number exceeds the main query's max pages. $paged > $_GET['pgs'] ) { $query->set( 'pg', $paged ); // for the custom query's pagination $query->set( 'paged', $_GET['pgs'] ); // for the main query's pagination // Prevent WordPress from redirecting to page/<max pages>. remove_action( 'template_redirect', 'redirect_canonical' ); } else { $query->set( 'pg', $query->get( 'paged' ) ); } } );
Then in the
bootstrap_pagination()
function, apply the four ([1]
to[4]
) changes below:// [1] Add the $use_alt function bootstrap_pagination( \WP_Query $wp_query = NULL, $echo = TRUE, $use_alt = null ) { ... // [2] Add these: $add_args = []; if ( $use_alt ) { $add_args['pgs'] = $GLOBALS['wp_query']->max_num_pages; } $pages = paginate_links( [ ... // [3] Use this instead. 'current' => max( 1, get_query_var( $use_alt ? 'pg' : 'paged' ) ), ... // [4] Use the $add_args 'add_args' => $add_args, ... ] ); ... }
Then in the archive/
taxonomy.php
template:// Define the $paged like so: $paged = max( 1, get_query_var( 'pg' ) ); // ... your code here. // Then call bootstrap_pagination() like so: bootstrap_pagination( $the_query, true, true );
Tried & tested working, but obviously as you can see above, once the max num pages for the main query has been reached, the next pages will set the paged
to that max num pages value. So it's up to you how to not make that "look bad/weird/whatever" and to handle things like performance (if your custom query had 20 extra pages than the main query, then one would see the main query's last page 20 times.. if they viewed them all).
If you facing the same issue so please go to the reading option page in settings and check how many numbers were set in the "Blog pages show at most" field value. if "Blog pages show at most" values are set greater than compared to your custom archive page or default page query string per page post parameter so you need to change the backend "Blog pages show at most" field value to match custom query per page post value.
For example :
"Blog pages show at most" field value is 12 and my custom query is
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'category',
'field' => 'id',
'include_children' => true,
'terms' => array(get_queried_object_id())
)
),
'paged' => $paged
);
$wp_query = new WP_Query($args);
As an above query, you see posts_per_page parameter value is 10 but still, we have set 12 in backend so it will cause an issue in pagination page because it will consider per page 12 posts so please change 12 to 10 and pagination will work properly, In my case, it works.
本文标签: Pagination Not Working for Custom Taxonomy with Custom Query404 Error
版权声明:本文标题:Pagination Not Working for Custom Taxonomy with Custom Query - 404 Error 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741330584a2372743.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
page_num
,pg
, etc. query string in the pagination URL. Butpaged
is reserved for the main query and it would result in the 404 error when the value is greater than the max number of pages for the main query. – Sally CJ Commented Jul 6, 2020 at 7:12