1

I have a wordpress instance full of custom post types called "games". Each game can have a rating. The main query on the frontpage uses this query:

public function my_modify_main_query( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) { // Run only on the homepage

        $query->set( 'post_type', array( 'game', 'post' ) );

        $query->set( 'tax_query', array(
            'relation' => 'OR',
            array(
                'taxonomy' => 'platform',
                'field'    => 'id',
                'terms'    => array(
                    3, //PS4
                    1312, //PC
                    158, //XBOX ONE
                    10158, //Switch
                ),
                'operator' => 'IN'
            )
        ) );
        $meta_query = array(
            array(
                'key'     => 'score_count',
                'value'   => '0',
                'type'    => 'numeric',
                'compare' => '>',
            ),
        );
        $query->set( 'meta_query', $meta_query );
    }

The result are all games which have a rating sorted by release date.

Since I always wanted to add an app for this page I started using WP-JSON. First, I tried to alter the main query of the wp-json endpoint after I added

'show_in_rest' => true

to the init of the custom post type: /wp-json/wp/v2/games

But I was unable to query for the same complex result only by using parameters.

So I started writing my own endpoint:

function shortscore_register_api_hooks() {
    $namespace = 'shortscore/v1';

    register_rest_route( $namespace, '/list-recent-rated-games/', array(
        'methods'  => 'GET',
        'callback' => 'shortscore_get_recent_rated_games',
    ) );
}
function shortscore_get_recent_rated_games() {
    if ( 0 || false === ( $result = get_transient( 'shortscore_recent_rated_games' ) ) ) {

        $args = array(
            'posts_per_page' => 10,
            'post_type'  => 'game',
            'tax_query',
            array(
                'relation' => 'OR',
                array(
                    'taxonomy' => 'platform',
                    'field'    => 'id',
                    'terms'    => array(
                        3, //PS4
                        1312, //PC
                        158, //XBOX ONE
                        10158, //Switch
                    ),
                    'operator' => 'IN'
                )
            ),
            'meta_query' => array(
                array(
                    'key'     => 'score_count',
                    'value'   => '0',
                    'type'    => 'numeric',
                    'compare' => '>',
                ),
            ),
        );

        $query = new WP_Query( $args );

        $rated_games = $query->posts;

        foreach ( $rated_games as $game ) {
            $result[] = array(
                'ID'           => $game->ID,
                'title'        => $game->post_title,
                'cover'        => get_the_post_thumbnail_url( $game->ID, array( 120, 120 ) ),
                'cover_double' => get_the_post_thumbnail_url( $game->ID, array( 240, 240 ) ),
                'permalink'    => get_permalink( $game->ID ),
                'score_count'  => intval( get_post_meta( $game->ID, 'score_count', true ) ),
                'score_value'  => intval( get_post_meta( $game->ID, 'score_value', true ) ),
            );
        }
        // cache for 10 minutes
        set_transient( 'shortscore_recent_rated_games', $result, 60 * 10 );
    }


    $response = new WP_REST_Response( $result );
    $response->header( 'Access-Control-Allow-Origin', apply_filters( 'shortscore_access_control_allow_origin', '*' ) );

    return $response;
}

This works well but in this case I would have to add a pagination on my own.

Is this the correct way to do this? Can't I just extend the main query and get all the things like pagination for free with x-headers and everything? How would you approach the problem? Add pagination to this custom endpoint or is there a way to extend the main query of WP-JSON with standard paramters for pagination?

  • 2
    I recently posted an example regarding the x-headers here, maybe that helps? – birgire Jul 23 '17 at 16:05
1

You are doing the right thing. In theory you can probably intercept the "normal" API request and modify the relevant wp_query to whatever you need, but this will mean that you are changing and overriding that API and if you will need it in its "virgin" form at some point it will not be available.

As for pagination, it is true that you need to make your own, but it is actually much easier to do that than on the HTML front end, all you need is to keep the page number in your JS handling routine and send the requested page as part of the request.

  • Thank you very much for reading my complex question @Mark Kaplun Maybe I am wrong but I thought that I need to implement pagination manually on my endpoint? I would have started using 'posts_per_page' => 10, 'paged' => $paged Or is there a hidden way to do this and I do not need to implement that for my last example with the custom endpoint? – Marc Jul 23 '17 at 18:18
  • 1
    there is no hidden way, and you do need to handle pagination by yourself, but all you need to add to your query is either an offset from which you want to get a post, or a page number if you support only N posts per request. This should be relatively trivial to add to the requests you are sending.... and you should look at the comment left by birgire – Mark Kaplun Jul 24 '17 at 4:04
  • Ok, thank you. I added paged, offset and per_page as parameters. – Marc Jul 24 '17 at 11:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.