How to add a custom parameter to a WP API default route?

I have created an opps custom post type and registered a custom API field of closed for it with the following code:

public function get_opp_state() {
    register_rest_field( 'opps', 'closed', array(
        'get_callback' => array( $this, 'get_opp_state_callback' ),
        'update_callback' => null,
        'schema' => null
    ));        
} 

public function get_opp_state_callback( $opp ) {  
    $oppDeadline = get_field( 'deadline', $opp[ 'id' ] ); 
    $today = date( 'Ymd' );
    $isClosed = $oppDeadline < $today; 
    return $isClosed;            
}                               

To retrieve all posts that use the opps post type, I use this request:

http://example.com/wp-json/wp/v2/opps

Now how can I extend that request to only fetch opps posts that have a closed field equal to true? I was hoping the following would work, but it doesn’t:

http://example.com/wp-json/wp/v2/opps?closed=true

I know I can create a custom route, but I really would like to avoid that since the information returned by the default request has all the info I need (except for that closed field). So is there any way to achieve this without a custom route?

2 Answers
2

After a lot of digging I seem to have found a solution myself, and a pretty powerful one, which makes use of a rest_{ post_type }_query filter (replace the { post_type } part with the slug of your custom post type. You can use rest_post_query to alter the default /wp-json/wp/v2/posts request):

public function __construct() {  
    // Make sure you add those numbers at the end of the line, or it won't work
    add_filter( 'rest_opps_query', array( $this, 'get_opps_by_state' ), 10, 2 );  
}  
       
public function get_opps_by_state( $args, $request ) {

    $state = $request->get_param( 'state' );  

    if( $state == 'open' ) {
        $args[ 'meta_query' ] = array(
            'deadline' => array(
                'key' => 'deadline',
                'value' => date( 'Ymd' ), 
                'compare' => '>',
                'type' => 'DATE'
            )
        );
    } elseif ( $state == 'closed' ) {
        $args[ 'meta_query' ] = array(
            'deadline' => array(
                'key' => 'deadline',
                'value' => date( 'Ymd' ), 
                'compare' => '<',
                'type' => 'DATE'
            )
        );
    }

    return $args; 

}

So now I can use the default WordPress API route to fetch custom posts:

http://example.com/wp-json/wp/v2/opps

and filter its results based on my custom parameter, status:

http://example.com/wp-json/wp/v2/opps?status=open

http://example.com/wp-json/wp/v2/opps?status=closed

No custom routes needed!

Leave a Comment