WordPress provides a robust and interactive way to extend its core functionality by providing the REST API. It enables us to perform create, update, read and delete operations on posts and custom posts types.

Registering Custom Routes

Before we start to create and read posts first we need to register routes to access this functionality.
In this example we useโ€”

  • GET /my_event: To retrieve posts of a custom post type called “my_event”
  • POST /my_event: To create new “my_event” posts via a POST request.

Registering the GET Route

We can register a route using the register_rest_route() function.

function my_event_posts_route() {
    register_rest_route( 'my/v1', '/my_event', array(
        'methods' => 'GET',
        'callback' => 'my_event_posts',
        'args' => array(
            'page' => array(
                'validate_callback' => function( $param, $request, $key ) {
                    return is_numeric( $param ) && $param > 0;
                },
                'default' => 1,
            ),
            'per_page' => array(
                'validate_callback' => function( $param, $request, $key ) {
                    return is_numeric( $param ) && $param > 0;
                },
                'default' => 10,
            ),
        ),
        'permission_callback' => '__return_true',
    ));
}
add_action( 'rest_api_init', 'my_event_posts_route' );
  • Validation: We need to validate that the page and per_page parameters are numeric.
  • Permission Callback: We set the permission callback to __return_true to make this router publicly accessible which is okay for a GET route.

Registering the POST Route

By settings the 'methods' parameter to POST we make sure that this route uses this HTTP method.

function my_create_event_post_route() {
    register_rest_route( 'my/v1', '/my_event', array(
        'methods' => 'POST',
        'callback' => 'my_create_event_post',
        'args' => array(
            'title' => array(
                'required' => true,
                'validate_callback' => function( $param, $request, $key ) {
                    return !empty( $param );
                },
            ),
            'content' => array(
                'required' => true,
                'validate_callback' => function( $param, $request, $key ) {
                    return !empty( $param );
                },
            ),
            'status' => array(
                'required' => true,
                'validate_callback' => function( $param, $request, $key ) {
                    return in_array( $param, ['publish', 'draft', 'pending'] );
                }
            ),
            'nonce' => array(
                'required' => true,
                'validate_callback' => function( $param, $request, $key ) {
                    return wp_verify_nonce( $param, 'my_create_event_nonce' );
                },
            ),
        ),
    ));
}
add_action( 'rest_api_init', 'my_create_event_post_route' );
  • Nonce Verification: We need to a nonce field for verifying if requests are legitimate. (nonce can be generated on the client side)
  • Sanitization: We need to use sanitize_text_field() for the title and sanitize_textarea_field() for the content to ensure inputs are safe to work with.

Callback to handle GET requests

function my_event_posts( $request ) {
    $args = array(
        'post_type' => 'my_event',
        'posts_per_page' => $request->get_param('per_page'),
        'paged' => $request->get_param('page'),
    );

    $query = new WP_Query( $args );

    if ( $query->have_posts() ) {
        $posts = array();
        while ( $query->have_posts() ) {
            $query->the_post();
            $posts[] = array(
                'id' => get_the_ID(),
                'title' => get_the_title(),
                'link' => get_permalink(),
            );
        }
        wp_reset_postdata();

        return new WP_REST_Response( array(
            'posts' => $posts,
            'pagination' => array(
                'total_pages' => $query->max_num_pages,
                'current_page' => $request->get_param('page'),
                'per_page' => $request->get_param('per_page'),
            ),
        ), 200);
    } else {
        return new WP_REST_Response(array(), 404);
    }
}

Callback Function to Handle POST Requests

function my_create_event_post( $request ) {
    // Ensure the user is logged in and has permission
    if ( !is_user_logged_in() || !current_user_can('publish_posts') ) {
        return new WP_Error(403, 'Unauthorized', array('status' => 403));
    }

    $title = sanitize_text_field( $request->get_param('title') );
    $content = sanitize_textarea_field( $request->get_param('content') );
    $status = sanitize_text_field( $request->get_param('status') );

    $new_post = array(
        'post_type' => 'my_event',
        'post_title' => $title,
        'post_content' => $content,
        'post_status' => $status,
        'post_date' => current_time('mysql'),
        'post_category' => array(0)
    );

    $post_id = wp_insert_post( $new_post );

    if ( !is_wp_error( $post_id ) ) {
        $post = get_post( $post_id );
        return new WP_REST_Response( $post, 201 );
    } else {
        return new WP_Error( 'post_creation_failed', 'Failed to create post', array( 'status' => 500 ) );
    }
}

Nonce Generation on the Client side

We can generate the nonce on the client side using JavaScript

wp_localize_script( 'script-handle', 'my_event', array(
    'nonce' => wp_create_nonce( 'my_create_event_nonce' )
));

Conclusion

Using the WordPress REST API to create and retrieve posts is a powerful way to interact with our WordPress site programmatically using the widely used JSON format. By incorporating these techniques we can build highly dynamic and responsive WordPress applications.

Leave a Reply

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