Implementation of JSON API specification for the Yii framework
PHP
Latest commit ea84908 Dec 23, 2016 @tuyakhov improve resource linkage

README.md

Implementation of JSON API specification for the Yii framework

Latest Stable Version Scrutinizer Code Quality Build Status Total Downloads

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist tuyakhov/yii2-json-api "*"

or add

"tuyakhov/yii2-json-api": "*"

to the require section of your composer.json file.

Data Serializing and Content Negotiation:

Controller:

class Controller extends \yii\rest\Controller
{
    public $serializer = 'tuyakhov\jsonapi\Serializer';

    public function behaviors()
    {
        return ArrayHelper::merge(parent::behaviors(), [
            'contentNegotiator' => [
                'class' => ContentNegotiator::className(),
                'formats' => [
                    'application/vnd.api+json' => Response::FORMAT_JSON,
                ],
            ]
        ]);
    }
}

Defining models: 1) Let's define User model and declare an articles relation

use tuyakhov\jsonapi\ResourceTrait;
use tuyakhov\jsonapi\ResourceInterface;

class User extends ActiveRecord implements ResourceInterface
{
    use ResourceTrait;

    public function getArticles()
    {
        return $this->hasMany(Article::className(), ['author_id' => 'id']);
    }
}

2) Now we need to define Article model

use tuyakhov\jsonapi\ResourceTrait;
use tuyakhov\jsonapi\ResourceInterface;

class Article extends ActiveRecord implements ResourceInterface
{
    use ResourceTrait;
}

3) As the result User model will be serialized into the proper json api resource object:

{
  "data": {
    "type": "users",
    "id": "1",
    "attributes": {
      // ... this user's attributes
    },
    "relationships": {
      "articles": {
        // ... this user's articles
      }
    }
  }
}

Controlling JSON API output

The JSON response is generated by the tuyakhov\jsonapi\JsonApiResponseFormatter class which will use the yii\helpers\Json helper internally. This formatter can be configured with different options like for example the $prettyPrint option, which is useful on development for better readable responses, or $encodeOptions to control the output of the JSON encoding.

The formatter can be configured in the yii\web\Response::formatters property of the response application component in the application configuration like the following:

'response' => [
    // ...
    'formatters' => [
        \yii\web\Response::FORMAT_JSON => [
            'class' => 'tuyakhov\jsonapi\JsonApiResponseFormatter',
            'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode
            'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
        ],
    ],
],

Links

Your resource classes may support HATEOAS by implementing the LinksInterface. The interface contains getLinks() method which should return a list of links. Typically, you should return at least the self link representing the URL to the resource object itself. In order to appear the links in relationships getLinks() method should return self link. Based on this link each relationship will generate self and related links. By default it happens by appending a relationship name at the end of the self link of the primary model, you can simply change that behavior by overwriting getRelationshipLinks() method. For example,

class User extends ActiveRecord implements ResourceInterface, LinksInterface
{
    use ResourceTrait;

    public function getLinks()
    {
        return [
            Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
        ];
    }
}

As the result:

{
  "data": {
    "type": "users",
    "id": "1",
    // ... this user's attributes
    "relationships": {
      "articles": {
        // ... article's data
        "links": {
            "self": {"href": "http://yourdomain.com/users/1/relationships/articles"},
            "related": {"href": "http://yourdomain.com/users/1/articles"}
        }
      }
    }
    "links": {
        "self": {"href": "http://yourdomain.com/users/1"}
    }
  }
}

Enabling JSON Input

To let the API accept input data in JSON API format, configure the [[yii\web\Request::$parsers|parsers]] property of the request application component to use the [[tuyakhov\jsonapi\JsonApiParser]] for JSON input

'request' => [
  'parsers' => [
      'application/vnd.api+json' => 'tuyakhov\jsonapi\JsonApiParser',
  ]
]