I’m trying to limit the content that is returned via REST API routes to only contain content published by the current logged in user. I’m trying to do this using pre_get_posts which works fine when in the admin view but the REST API output is still including all posts.

In this case I am trying to do it via the REST route for a custom post type, so the route is /wp-json/wp/v2/todos/. Accessing this route works fine by default and returns all posts, but with my pre_get_posts code in place it still always returns all posts. Here is my pre_get_posts code:

function only_users_todos( $query ) {
    global $user_ID;
    $query->set( 'author', $user_ID );
    return $query;
}
add_filter( 'pre_get_posts', 'only_users_todos' );

Am I missing something obvious here, or does pre_get_posts just not get called for REST API requests?

1 Answer
1

Yes, pre_get_posts runs for REST API requests. Your issue is likely that your request is not properly authenticated, so $user_ID is not set. To allow the REST API to recognise the logged-in user you need to send the wp_rest nonce with the request. You can create this with wp_create_nonce( 'wp_rest' ) and send it with the request as the X-WP-Nonce header. This is documented in more detail in the developer handbook.

It’s not relevant to your original question, but the code in your question will apply to all queries. This includes posts, pages, menus etc. So if you won’t want that behaviour you need to add some sort of check so that your code only applies to certain queries. For example:

function only_users_todos( $query ) {
    if ( $query->get( 'post_type' ) === 'todo' ) {
        $query->set( 'author', get_current_user_id() );
    }
}
add_action( 'pre_get_posts', 'only_users_todos' );

Also, pre_get_posts is an action, not a filter, so you don’t need to return $query.

Leave a Reply

Your email address will not be published. Required fields are marked *