- Published on
How to make your CakePHP 3 API produce JSON API
In this follow-up post to How to add JWT Authentication to a CakePHP 3 REST API we will update our existing API so it will produce JSON API compliant output giving you the benefits of standardization and instant compatibility with JSON API supporting tools like Ember Data.
> API methods used in this post shared with Postman
Before We Begin
This is part five of the CakePHP 3 REST API tutorial series:
- How to build a CakePHP 3 REST API in minutes
- How to use a CakePHP 3 REST API
- How to prefix route a CakePHP 3 REST API
- How to add JWT Authentication to a CakePHP 3 REST API
- How to make your CakePHP 3 API produce JSON API
- How to use a CakePHP API as the data backend for Ember in 30 minutes
Before starting this tutorial either:
- Complete the previous tutorial
- Start fresh by using these end-state application sources, composer installing and running the database migration
1. Install required packages
To make sure your API is using an up-to-date version of CakePHP and the required version of the Crud plugin now update your project's composer packages by running:
composer update
Update Crud to at least version 5.0.0:
composer require friendsofcake/crud:^5.0
Remove any previous version of the neomerx package:
composer remove neomerx/json-api
Lastly, add the Crud JsonApi listener to your application by running:
composer require friendsofcake/crud-json-api
2. Disable JWT authentication
Since JWT authentication is unrelated to JSON API we will disable it by removing the related lines in src/Controller/Api/AppController
which should leave you with a file looking like this:
<?php
namespace App\Controller\Api;
use Cake\Controller\Controller;
use Cake\Event\Event;
/**
* AppController specific to API resources
*/
class AppController extends Controller
{
use \Crud\Controller\ControllerTrait;
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete'
],
'listeners' => [
'Crud.Api',
'Crud.ApiPagination',
'Crud.ApiQueryLog'
]
]);
}
}
Even though the CakePHP and Crud upgrades were totally transparent while writing this post this might be a good moment to verify that your API's
cocktails
endpoint is still producing the expected results using GET, POST, etc.
3. Enable JSON API
All that is needed now to make your API produce JSON API is opening src/Controller/Api/AppController
and replacing the Crud.Api
listener with Crud.JsonAPi
so it looks like:
'listeners' => [
'CrudJsonApi.JsonApi',
'CrudJsonApi.Pagination', // Pagination != ApiPagination
'Crud.ApiQueryLog'
]
All done, seriously.
4. Using the new API
Please note that the JsonApiListener documentation contains very detailed usage descriptions and since there no point in duplicating them here we will provide you with just two basic examples to get you going.
The Postman collection contains examples of
index
,view
,add
,edit
anddelete
.
Never forget:
- ALL requests to your new API MUST use the
application/vnd.api+json
Accept Header - ALL requests with post data MUST use the
application/vnd.api+json
Content-Type Header
View action (GET)
For this example we are in the mood for a Mojito so we query http://cake3api.app/cocktails/3
making sure we are using:
- HTTP Method
GET
- Accept Header
application/vnd.api+json
If things went well your API should return Status Code 200 (Success) with a response body in JSON API format looking similar to:
{
"data": {
"type": "cocktails",
"id": "3",
"attributes": {
"name": "Mojito",
"description": "Rum based",
"created": "2015-04-11T09:52:01+00:00",
"modified": null
},
"links": {
"self": "/api/cocktails/3"
}
}
}
Add action (POST)
To create a new cocktail send a JSON API request to http://cake3api.app/cocktails
making sure you are using:
- HTTP Method
GET
- Accept Header
application/vnd.api+json
- Content-Type Header
application/vnd.api+json
Also make sure to set the full or partial body data in (absolutely) correct JSON API format, e.g:
{
"data": {
"type": "cocktails",
"attributes": {
"name": "Some cocktail",
"description": "Some description"
}
}
}
Now send the request.
If things went well your API should return Status Code 201 (Success) with a response body in JSON API format looking similar to:
{
"data": {
"type": "cocktails",
"id": "24",
"attributes": {
"name": "Some name",
"description": "None inspired description",
"created": "2017-03-16T19:01:57+00:00",
"modified": "2017-03-16T19:01:57+00:00"
},
"links": {
"self": "/api/cocktails/24"
}
}
}
5. Enabling CORS middleware
Your API will be pretty useless if people (from other domains) won't be able to use it so let's enable it right now along with CakePHP's new middleware functionality by following the book's step-by-step instructions :
- Update
webroot/index.php
- Create
src/Application.php
by copying from the cakephp-app repo
Now that our application is capable of handling middleware let's add the cakephp-cors middleware plugin by running:
composer require ozee31/cakephp-cors
Enable the plugin by adding this to config/bootstrap.php
:
Plugin::load('Cors', ['bootstrap' => true, 'routes' => false]);
To complete, specify the correct ExceptionRenderers in config/app.php
so the JSON API (validation) errors keep functioning as expected whilst also respecting CORS headers:
'Error' => [
'errorLevel' => E_ALL & ~E_DEPRECATED,
'exceptionRenderer' => '\Crud\Error\JsonApiExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
'Cors' => [
'exceptionRenderer' => '\Cors\Error\AppExceptionRenderer'
],
Please note that the plugin will allow CORS for all origins, all methods and all headers by default which is a very good thing as we will start using CORS pretty heavily in the next tutorial.
Additional reading
- Crud JsonApiListener documentation
- Follow-up tutorial How to use a CakePHP API as the data backend for Ember in 30 minutes
- Crud JsonApiListener documentation
- Git repository with working end state application as produced by this tutorial
- neomerx/jsonapi