#41866 closed defect (bug) (invalid)
REST API throws error when displaying an unlimited number of posts in a request
Reported by: | dpsjfveloso1 | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 4.9 |
Component: | REST API | Keywords: | |
Focuses: | rest-api | Cc: |
Description
Hi there,
The REST API posts/pages endpoints fails when using a filter to set the posts_per_page as -1, it throws a WP_Error, rest_post_invalid_page_number, as the number of max pages, $max_pages, is negative as the posts_per_page has a negative value (-1).
The error can be reproduced by applying a filter for the rest_page_query filter, setting the posts_per_page argument as -1:
<?php function remove_posts_limits( array $arguments = array(), \WP_REST_Request $restApiRequest ) { // Let's suppose that we want to remove the number of posts per page as unlimited under certain conditions, and this is the reason why we use this filter $arguments[ 'posts_per_page' ] = -1; return $arguments; } add_filter( 'rest_page_query', 'remove_posts_limits', 10, 2);
The issue is caused due to the way that $max_pages is set (file /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php, starts at line 326):
<?php /* . . . */ $max_pages = ceil( $total_posts / (int) $posts_query->query_vars['posts_per_page'] ); if ( $page > $max_pages && $total_posts > 0 ) { return new WP_Error( 'rest_post_invalid_page_number', __( 'The page number requested is larger than the number of pages available.' ), array( 'status' => 400 ) ); } /* . . . */
The simplest solution here would be to use the abs() after casting posts_per_page value:
<?php /* . . . */ $max_pages = ceil( $total_posts / abs( (int) $posts_query->query_vars['posts_per_page'] ) ); /* . . . */
But the $max_pages could also be set inside of an if clause, as the value of $max_pages should be one in all cases (this would be a better solution):
<?php /* . . . */ $posts_per_page = (int) $posts_query->query_vars['posts_per_page']; $max_pages = ceil( $total_posts / $posts_per_page ); if ($posts_per_page < 0) { // It's an unlimited number of posts per page, which means that $max_pages must be 1 $max_pages = 1; } /* . . . */
Thanks,
Jorge
Change History (4)
#4
@
2 years ago
I am getting the same problem on WP version 6.1.1.
Using the REST URL '/wp-json/wp/v2/events/' I am fetching all events posts. My code is modifying the wp-query object to set posts_per_page = -1 via pre_get_posts hook.
<?php add_action( 'pre_get_posts', array($this, 'qw_pre_get_posts') ); function qw_pre_get_posts( $query ){ if( !is_admin() && !is_home() && !is_page()){ $meta_query = array( 'relation' => 'OR', array( 'key' => 'sticky', 'value' => array(1, '1', true, 0, '0', false, 'on') ), array( 'key' => '_qw_events_date', ) ); $query->set( 'meta_query', $meta_query ); $query->set( 'orderby', 'meta_value' ); $query->set('meta_key', '_qw_events_date'); $query->set('order', 'ASC'); $query->set('posts_per_page', -1); } }
REST RESPONSE:
[{"id":1468,"date":"2022-07-29T13:14:37","date_gmt":"2022-07-29T17:14:37","guid":{"rendered":"http:\/\/example.com\/?post_type=events&p=1468"},"modified":"2022-11-14T09:58:50","modified_gmt":"2022-11-14T13:58:50","slug":"greensboro-symphony-with-michael-feinstein","type":"events","link":"https:\/\/example.com\/events......
My code was working perfectly on WP version 4.6.25. After updating to version 6.1.1 I am getting the following response from REST API.
REST RESPONSE:
'
{"code":"rest_post_invalid_page_number","message":"The page number requested is larger than the number of pages available.","data":{"status":400}}
'
If I disable the line '$query->set('posts_per_page', -1);' REST API returns event post data.
Hi @dpsjfveloso1,
Thanks for taking the time to make this report, and welcome to Trac! This particular behavior is by design. As described in this comment from the WP-API GitHub repo, querying for all posts should be done via iteration, rather than a single massive query.