Documentation
Services Provider
REST API

REST API

WP Bones provides a simple way to create your own REST API. You may use the WordPress REST API as well.

You'll find more info here (opens in a new tab)

Configuration

First of all, we have added a new api.php configuration file to the config folder. You'll find some useful settng to handle the embeded WordPress Rest API and your custome own endpoints.

config/api.php
<?php
 
/*
|--------------------------------------------------------------------------
| WordPress REST API configuration
|--------------------------------------------------------------------------
|
| Here is where you can set up the WordPress REST API features.
|
*/
 
return [
 
  // embedded wp-json-server
  'wp'     => [
    'require_authentication' => false, // will affect all routes.
  ],
 
  // your custom rest api
  'custom' => [
    'path'    => '/api',
    'enabled' => true,
  ],
 
  // authentication
  'auth'   => [
    // embed basic authentication handler
    'basic' => true,
  ],
];

Create your first API

To create your custom API, you have to create a new folder into /api in the root of your plugin.

đź’ˇ

You may change the name of your folder, but you'll have to change the path in the api.php configuration file.

The main folder will be the vendor. Usually, into the vendor folder you'll create the version folder as well. For example, you may create

  • Routing

    Now, we can start to create the Rest API route by adding a new file in the our structure.

    For example, we'll use route.php

        • route.php
  • Let's see a simple implementation of route.php

    api/vendor/v1/route.php
    use WPKirk\WPBones\Routing\API\Route;
     
    Route::get('/example', function () {
        return 'Hello World!';
    });

    You may use your browser to test /api/vendor/v1/example route.

    HTTP Methods

    The Route class supports the following HTTP methods: get, post, put, patch, delete

    In short, the same supported by the WordPress REST API and defined in the WP_REST_Server class.

    api/vendor/v1/route.php
    use WPKirk\WPBones\Routing\API\Route;
     
    Route::post('/example', function () {
        return 'Hello World!';
    });

    Instead of use the static method Route::get(), Route::post(), and so on, you can use the ::request() instead. You will be able to use multiple HTTP verbs at the same time.

    api/vendor/v1/route.php
    use WPKirk\WPBones\Routing\API\Route;
     
    Route::request('get', '/get_request', function () {
        return 'Hello World!';
    });
     
    // HTTP verb is case insensitive
    Route::request('GET', '/get_request', function () {
        return 'Hello World!';
    });
     
    // you may use both strings and arrays
    Route::request(['get'], '/get_request', function () {
        return 'Hello World!';
    });
     
    // you may use multiple HTTP verbs
    Route::request(['get', 'POST'], '/multiple', function () {
        return 'Hello World!';
    });

    WP_REST_Request injection

    You will be able to get the WP_REST_Request object from the function used in the Route class.

    api/vendor/v1/route.php
    use WPKirk\WPBones\Routing\API\Route;
     
    Route::get('/example_args', function (\WP_REST_Request $request) {
        $value = var_export($request, true);
     
        /**
         *   // You can access parameters via direct array access on the object:
         *   $param = $request['some_param'];
         *
         *   // Or via the helper method:
         *   $param = $request->get_param( 'some_param' );
         *
         *   // You can get the combined, merged set of parameters:
         *   $parameters = $request->get_params();
         *
         *   // The individual sets of parameters are also available, if needed:
         *   $parameters = $request->get_url_params();
         *   $parameters = $request->get_query_params();
         *   $parameters = $request->get_body_params();
         *   $parameters = $request->get_json_params();
         *   $parameters = $request->get_default_params();
         *
         *   // Uploads aren't merged in, but can be accessed separately:
         *   $parameters = $request->get_file_params();
         */
     
        return 'Hello World!';
    });

    JSON Response

    Of course, you may return a JSON response by using the WordPress wp_send_json() function.

    use WPKirk\WPBones\Routing\API\Route;
     
    // json response
    Route::get('/example_json', function () {
        wp_send_json(["tag" => "v1.0.0"]);
    });

    You may use also the response() static method provides by the Route class.

    use WPKirk\WPBones\Routing\API\Route;
     
    // right way to use a simple response
    Route::get('/example_response', function () {
        return Route::response(["tag" => "v1.0.0"]);
    });

    Error Response

    The best practice is to return a WP_Error object.

    use WPKirk\WPBones\Routing\API\Route;
     
    // invalide example
    Route::get('/invalid', function () {
        return new \WP_Error('no_author', 'Invalid author', [ 'status' => 404 ]);
    });

    Also in this case, you may use the responseError() static method provides by the Route class.

    use WPKirk\WPBones\Routing\API\Route;
     
    // right way to use an error response
    Route::get('/error', function () {
        return Route::responseError('no_author', 'Invalid author', [ 'status' => 404 ]);
    });

    RestController

    Of course, you may use a RestController to handle the request. WPBones provides a simple way to create a new controller.

    You may create your own controller extending the RestController class. For example, lets create a new controller called WPKirkV1Controller in the wp-content/plugins/WPKirk/plugin/API/WPKirkV1Controller.php folder.

    namespace WPKirk\API;
     
    use WPKirk\WPBones\Routing\API\RestController;
     
    class WPKirkV1Controller extends RestController
    {
        public function version()
        {
            return $this->response(['version' => '1.0.0']);
        }
    }

    Using the php bones make:api Bones command, we can quickly create a RestController.

    Now, in the route.php file, you may use the WPKirkV1Controller.

    use WPKirk\WPBones\Routing\API\Route;
     
    // may use the same route for different methods
    Route::get('/version', '\WPKirk\API\WPKirkV1Controller@version');

    WP_REST_Request and vendor injection

    By usign a RestController you may get the WP_REST_Request object and the vendor information in different ways. The first one is using the property request of the RestController class.

    namespace WPKirk\API;
     
    use WPKirk\WPBones\Routing\API\RestController;
     
    class WPKirkV1Controller extends RestController
    {
        public function version()
        {
            // get the request object and log the method
            logger()->debug("REQUEST get_method", $this->request->get_method());
     
            return $this->response(['version' => '1.0.0']);
        }
    }

    Of course, feel free to check the WordPress documentation for more information about the WP_REST_Request object.

    The second way is using inject object in method directly.

    namespace WPKirk\API;
     
    use WPKirk\WPBones\Routing\API\RestController;
     
    class WPKirkV1Controller extends RestController
    {
        public function version($request)
        {
            // get the request object and log the method
            logger()->debug("REQUEST get_method", $request->get_method());
     
            return $this->response(['version' => '1.0.0']);
        }
    }

    The vendor information, instead, is available in the property vendor of the RestController class. You will get all paths along with any version information. For instance wpkirk/v1 in our example.

    namespace WPKirk\API;
     
    use WPKirk\WPBones\Routing\API\RestController;
     
    class WPKirkV1Controller extends RestController
    {
        public function version($request)
        {
            // get the request object and log the method
            logger()->debug("Vendor", $request->vendor); // for example, "wpkirk/v1"
     
            return $this->response(['version' => '1.0.0']);
        }
    }

    Authentication

    WPBones will add the Basic Authentication features without use the official WordPress Plugin (opens in a new tab). The Basic Authentication is based on the WordPress Basic Authentication (opens in a new tab) and the WordPress Basic Authentication Plugin (opens in a new tab).

    Remember that you have to enebale this feature from api.php configuration file.

    config/api.php
    <?php
    /*
    |--------------------------------------------------------------------------
    | WordPress REST API configuration
    |--------------------------------------------------------------------------
    |
    | Here is where you can set up the WordPress REST API features.
    |
    */
     
    return [
     
        // authentication
        'auth' => [
            // embed basic authentication handler
            'basic' => true
        ]
    ]

    Options

    You may add additional options to the Route following the WordPress REST para

    use WPKirk\WPBones\Routing\API\Route;
     
    Route::get('/example', function () {
        return 'Hello World!';
    }, ['permission_callback' => function () {
        return false;
    }]);

    In the above example you'll receive

     {"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":401}}

    Of course, you may do the same with the RestController as well

    use WPKirk\WPBones\Routing\API\Route;
     
    Route::get('/version', '\WPKirk\API\WPKirkV1Controller@version', [
        'permission_callback' => function () {
            return false;
        }]);
    {"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":401}}

    Disable the WordPress REST API

    You should not disable the REST API; doing so will break WordPress Admin functionality that depends on the API being active. However, you may use a filter to require that API consumers be authenticated, which effectively prevents anonymous external access.

    Anyway, you can require authentication for all REST API requests by setting the require_authentication to true in the configuration file.

    config/api.php
    <?php
     
    /*
    |--------------------------------------------------------------------------
    | WordPress REST API configuration
    |--------------------------------------------------------------------------
    |
    | Here is where you can set up the WordPress REST API features.
    |
    */
     
    return [
     
        // embeded wp-json-server
        'wp' => [
            'require_authentication' => true
        ],
    ]
    đź’ˇ

    The above setting will affect all routes. From a browser request, you won't receive the error message if you're logged in.