pagination - When to check for max_num_pages using Wordpress REST API?

I'm implementing infinite loading using the WP API, so I pull in the new posts via an API request. Because the defa

I'm implementing infinite loading using the WP API, so I pull in the new posts via an API request. Because the default API response is fine with me and I only really need to filter the posts returned, I'm not creating a custom route but rather customizing the default query:

add_filter( 'rest_post_query', array( $this, 'get_posts' ), 10, 2 );

public function get_posts( $args, $req ) {    

    /*
    This function is used to retrieve posts of the 'post' and 'news' type
    */

    $cat = $req[ 'category' ];
    $page = $req[ 'page' ];  
    $tag = $req[ 'tag' ];
    $type = $req[ 'type' ]; 

    $args[ 'paged' ] = isset( $page ) ? $page : 1;
    $args[ 'posts_per_page' ] = 8;  
    $args[ 'category_name' ] = isset( $cat ) && ! empty( $cat ) ? $cat : null;
    $args[ 'tag' ] = isset( $tag ) && ! empty( $tag ) ? $tag : null;
    $args[ 'post_type' ] = 
        isset( $type ) && ! empty( $type ) ? array( $type ) : array( 'post', 'news' ); 

    return $args;

}

I have a problem with pagination, though. Imagine that I have 10 pages of results and I request page 20: the API's default behavior is to throw the following error:

{
    "code": "rest_post_invalid_page_number",
    "message": "The page number requested is larger than the number of pages available.",
    "data": {
        "status": 400
    }
}

What I would like to do is return an empty array instead, because it would be easier and more intuitive to deal with in the frontend. So I thought I'd check the max_num_pages property of the query, but I don't know where to do that.

I tried doing this:

add_action( 'pre_get_posts', array( $this, 'check_pagination_limit' ) ); 

public function check_pagination_limit( $query ) {
    if( ! is_admin() ) {
        $currentPage = $query->get('paged'); 
        $lastPage = $query->max_num_pages; 
        if( $currentPage > $lastPage ) {
            $query->set('post__in', array(0)); 
        }
    }
}

But pre_get_posts doesn't seem to work well when rest_post_query is being used... Is there any rest_ filter or hook that I can use to access the query before the response is sent?

I'm implementing infinite loading using the WP API, so I pull in the new posts via an API request. Because the default API response is fine with me and I only really need to filter the posts returned, I'm not creating a custom route but rather customizing the default query:

add_filter( 'rest_post_query', array( $this, 'get_posts' ), 10, 2 );

public function get_posts( $args, $req ) {    

    /*
    This function is used to retrieve posts of the 'post' and 'news' type
    */

    $cat = $req[ 'category' ];
    $page = $req[ 'page' ];  
    $tag = $req[ 'tag' ];
    $type = $req[ 'type' ]; 

    $args[ 'paged' ] = isset( $page ) ? $page : 1;
    $args[ 'posts_per_page' ] = 8;  
    $args[ 'category_name' ] = isset( $cat ) && ! empty( $cat ) ? $cat : null;
    $args[ 'tag' ] = isset( $tag ) && ! empty( $tag ) ? $tag : null;
    $args[ 'post_type' ] = 
        isset( $type ) && ! empty( $type ) ? array( $type ) : array( 'post', 'news' ); 

    return $args;

}

I have a problem with pagination, though. Imagine that I have 10 pages of results and I request page 20: the API's default behavior is to throw the following error:

{
    "code": "rest_post_invalid_page_number",
    "message": "The page number requested is larger than the number of pages available.",
    "data": {
        "status": 400
    }
}

What I would like to do is return an empty array instead, because it would be easier and more intuitive to deal with in the frontend. So I thought I'd check the max_num_pages property of the query, but I don't know where to do that.

I tried doing this:

add_action( 'pre_get_posts', array( $this, 'check_pagination_limit' ) ); 

public function check_pagination_limit( $query ) {
    if( ! is_admin() ) {
        $currentPage = $query->get('paged'); 
        $lastPage = $query->max_num_pages; 
        if( $currentPage > $lastPage ) {
            $query->set('post__in', array(0)); 
        }
    }
}

But pre_get_posts doesn't seem to work well when rest_post_query is being used... Is there any rest_ filter or hook that I can use to access the query before the response is sent?

Share Improve this question asked Mar 22, 2019 at 7:56 grazdevgrazdev 1,3333 gold badges14 silver badges26 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

pre_get_posts does fire for REST requests.

After copying your function and stepping through it, your code is actually working -- the first time. However the WP REST controller has the following bit:

        if ( $total_posts < 1 ) {
            // Out-of-bounds, run the query again without LIMIT for total count.
            unset( $query_args['paged'] );

            $count_query = new WP_Query();
            $count_query->query( $query_args );
            $total_posts = $count_query->found_posts;
        }

This re-runs the query, which in turn re-runs your function. However as you can see, it has intentionally unset the 'paged' argument, so this time when you compare $currentPage > $lastPage you are comparing 0 > 0 which is false, so your post__in argument is not set, and posts are returned. You know the rest of the story -- WordPress then catches that you can't have that page because there aren't enough posts.

You could get that parameter more directly since it is part of your GET request, like:

    if( ! is_admin()
        && isset($_GET['page']) ) {
        $currentPage = $_GET['page'];
        $lastPage = $query->max_num_pages;
        if( $currentPage > $lastPage ) {
            $query->set('post__in', array(0));
        }
    }

This seemed to work, but I didn't test it thoroughly.

To be honest, you are really swimming upstream here, and I think a better solution might be to take a hint from WordPress and just build in handling for that error response. It's nicely packaged as JSON, and you will probably want to watch for other errors too anyways.

Also, I think your function should check and make sure it is only firing on REST requests. Right now as it is written it would fire on others as well.

Note that the rest response header for naitve endpoints contains information about the number of found items and total number of pages:

X-WP-Total: 10
X-WP-TotalPages: 1

This would be available via javascript and can help with the pagination on the front-end.

Check it with e.g.

curl -I https://example/wp-json/wp/v2/posts

from your command line.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745665203a4639080.html

相关推荐

  • pagination - When to check for max_num_pages using Wordpress REST API?

    I'm implementing infinite loading using the WP API, so I pull in the new posts via an API request. Because the defa

    21天前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信