diff --git a/.gitignore b/.gitignore
index 0c46198..04167d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ Thumbs.db
 
 # composer itself is not needed
 composer.phar
+composer.lock
 
 # Mac DS_Store Files
 .DS_Store
diff --git a/README.md b/README.md
index 0bec2c0..26ca03c 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
+<p align="center"><img width="30%" src ="https://jsonapi.org/images/jsonapi.png" /></p>
 
 Implementation of JSON API specification for the Yii framework
 ==================================================================
 [![Latest Stable Version](https://poser.pugx.org/tuyakhov/yii2-json-api/v/stable.png)](https://packagist.org/packages/tuyakhov/yii2-json-api)
 [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/tuyakhov/yii2-json-api/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/tuyakhov/yii2-json-api/?branch=master) [![Build Status](https://scrutinizer-ci.com/g/tuyakhov/yii2-json-api/badges/build.png?b=master)](https://scrutinizer-ci.com/g/tuyakhov/yii2-json-api/build-status/master)
 [![Total Downloads](https://poser.pugx.org/tuyakhov/yii2-json-api/downloads.png)](https://packagist.org/packages/tuyakhov/yii2-json-api)
+
 Installation
 ------------
 
@@ -166,6 +168,12 @@ As the result:
   }
 }
 ```
+Pagination
+---------------------------
+The `page` query parameter family is reserved for pagination.
+This library implements a page-based strategy and allows the usage of query parameters such as `page[number]` and `page[size]`  
+Example: `http://yourdomain.com/users?page[number]=3&page[size]=10`
+
 Enabling JSON API 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
@@ -208,3 +216,117 @@ $model->load(\Yii::$app->request->post());
 By default type `users` will be converted into `User` (singular, camelCase) which corresponds to the model's `formName()` method (which you may override).
 You can override the `JsonApiParser::formNameCallback` property which refers to a callback that converts 'type' member to form name.
 Also you could change the default behavior for conversion of member names to variable names ('first-name' converts into 'first_name') by setting `JsonApiParser::memberNameCallback` property.
+
+Examples
+--------
+Controller:
+```php
+class UserController extends \yii\rest\Controller
+{
+    public $serializer = 'tuyakhov\jsonapi\Serializer';
+
+    /**
+     * @inheritdoc
+     */
+    public function behaviors()
+    {
+        return ArrayHelper::merge(parent::behaviors(), [
+            'contentNegotiator' => [
+                'class' => ContentNegotiator::className(),
+                'formats' => [
+                    'application/vnd.api+json' => Response::FORMAT_JSON,
+                ],
+            ]
+        ]);
+    }
+    
+    /**
+     * @inheritdoc
+     */
+    public function actions()
+    {
+        return [
+            'create' => [
+                'class' => 'tuyakhov\jsonapi\actions\CreateAction',
+                'modelClass' => ExampleModel::className()
+            ],
+            'update' => [
+                'class' => 'tuyakhov\jsonapi\actions\UpdateAction',
+                'modelClass' => ExampleModel::className()
+            ],
+            'view' => [
+                'class' => 'tuyakhov\jsonapi\actions\ViewAction',
+                'modelClass' => ExampleModel::className(),
+            ],
+            'delete' => [
+                'class' => 'tuyakhov\jsonapi\actions\DeleteAction',
+                'modelClass' => ExampleModel::className(),
+            ],
+            'view-related' => [
+                'class' => 'tuyakhov\jsonapi\actions\ViewRelatedAction',
+                'modelClass' => ExampleModel::className()
+            ],
+            'update-relationship' => [
+                'class' => 'tuyakhov\jsonapi\actions\UpdateRelationshipAction',
+                'modelClass' => ExampleModel::className()
+            ],
+            'delete-relationship' => [
+                'class' => 'tuyakhov\jsonapi\actions\DeleteRelationshipAction',
+                'modelClass' => ExampleModel::className()
+            ],
+            'options' => [
+                'class' => 'yii\rest\OptionsAction',
+            ],
+        ];
+    }
+}
+
+```
+
+Model:
+```php
+class User extends ActiveRecord implements LinksInterface, ResourceInterface
+{
+    use ResourceTrait;
+    
+    public function getLinks()
+    {
+        $reflect = new \ReflectionClass($this);
+        $controller = Inflector::camel2id($reflect->getShortName());
+        return [
+            Link::REL_SELF => Url::to(["$controller/view", 'id' => $this->getId()], true)
+        ];
+    }
+}
+```
+
+Configuration file `config/main.php`:
+```php
+return [
+    // ...
+    'components' => [
+        'request' => [
+            'parsers' => [
+                'application/vnd.api+json' => 'tuyakhov\jsonapi\JsonApiParser',
+            ]
+        ],
+        'response' => [
+            'format' => \yii\web\Response::FORMAT_JSON,
+            'formatters' => [
+                \yii\web\Response::FORMAT_JSON => 'tuyakhov\jsonapi\JsonApiResponseFormatter'
+            ]
+        ],
+        'urlManager' => [
+            'rules' => [
+                [
+                    'class' => 'tuyakhov\jsonapi\UrlRule',
+                    'controller' => ['user'],
+                ],
+
+            ]
+        ]
+        // ...
+    ]
+    // ...
+]
+```
diff --git a/composer.json b/composer.json
index 7b78444..76072ec 100644
--- a/composer.json
+++ b/composer.json
@@ -17,14 +17,18 @@
     }
   ],
   "require": {
-    "yiisoft/yii2": "^2.0.10"
+    "yiisoft/yii2": "^2.0.13"
   },
   "require-dev": {
     "phpunit/phpunit": "5.5.*"
   },
   "autoload": {
     "psr-4": {
-      "tuyakhov\\jsonapi\\": "src/",
+      "tuyakhov\\jsonapi\\": "src/"
+    }
+  },
+  "autoload-dev": {
+    "psr-4": {
       "tuyakhov\\jsonapi\\tests\\": "tests/"
     }
   }
diff --git a/composer.lock b/composer.lock
deleted file mode 100644
index 042c2f6..0000000
--- a/composer.lock
+++ /dev/null
@@ -1,1706 +0,0 @@
-{
-    "_readme": [
-        "This file locks the dependencies of your project to a known state",
-        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
-        "This file is @generated automatically"
-    ],
-    "hash": "90fe276d27f5f93d6bc833a682829636",
-    "content-hash": "668e9cd59b0ef219b1eec0e83f18bb36",
-    "packages": [
-        {
-            "name": "bower-asset/jquery",
-            "version": "2.2.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/jquery/jquery-dist.git",
-                "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72",
-                "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72",
-                "shasum": ""
-            },
-            "type": "bower-asset-library",
-            "extra": {
-                "bower-asset-main": "dist/jquery.js",
-                "bower-asset-ignore": [
-                    "package.json"
-                ]
-            },
-            "license": [
-                "MIT"
-            ],
-            "keywords": [
-                "browser",
-                "javascript",
-                "jquery",
-                "library"
-            ]
-        },
-        {
-            "name": "bower-asset/jquery.inputmask",
-            "version": "3.2.7",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/RobinHerbots/jquery.inputmask.git",
-                "reference": "5a72c563b502b8e05958a524cdfffafe9987be38"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/5a72c563b502b8e05958a524cdfffafe9987be38",
-                "reference": "5a72c563b502b8e05958a524cdfffafe9987be38",
-                "shasum": ""
-            },
-            "require": {
-                "bower-asset/jquery": ">=1.7"
-            },
-            "type": "bower-asset-library",
-            "extra": {
-                "bower-asset-main": [
-                    "./dist/inputmask/inputmask.js"
-                ],
-                "bower-asset-ignore": [
-                    "**/*",
-                    "!dist/*",
-                    "!dist/inputmask/*",
-                    "!dist/min/*",
-                    "!dist/min/inputmask/*",
-                    "!extra/bindings/*",
-                    "!extra/dependencyLibs/*",
-                    "!extra/phone-codes/*"
-                ]
-            },
-            "license": [
-                "http://opensource.org/licenses/mit-license.php"
-            ],
-            "description": "jquery.inputmask is a jquery plugin which create an input mask.",
-            "keywords": [
-                "form",
-                "input",
-                "inputmask",
-                "jquery",
-                "mask",
-                "plugins"
-            ]
-        },
-        {
-            "name": "bower-asset/punycode",
-            "version": "v1.3.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/bestiejs/punycode.js.git",
-                "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3",
-                "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3",
-                "shasum": ""
-            },
-            "type": "bower-asset-library",
-            "extra": {
-                "bower-asset-main": "punycode.js",
-                "bower-asset-ignore": [
-                    "coverage",
-                    "tests",
-                    ".*",
-                    "component.json",
-                    "Gruntfile.js",
-                    "node_modules",
-                    "package.json"
-                ]
-            }
-        },
-        {
-            "name": "bower-asset/yii2-pjax",
-            "version": "v2.0.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/yiisoft/jquery-pjax.git",
-                "reference": "60728da6ade5879e807a49ce59ef9a72039b8978"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978",
-                "reference": "60728da6ade5879e807a49ce59ef9a72039b8978",
-                "shasum": ""
-            },
-            "require": {
-                "bower-asset/jquery": ">=1.8"
-            },
-            "type": "bower-asset-library",
-            "extra": {
-                "bower-asset-main": "./jquery.pjax.js",
-                "bower-asset-ignore": [
-                    ".travis.yml",
-                    "Gemfile",
-                    "Gemfile.lock",
-                    "CONTRIBUTING.md",
-                    "vendor/",
-                    "script/",
-                    "test/"
-                ]
-            },
-            "license": [
-                "MIT"
-            ]
-        },
-        {
-            "name": "cebe/markdown",
-            "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/cebe/markdown.git",
-                "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/cebe/markdown/zipball/c30eb5e01fe021cc5bba2f9ee0eeef96d4931166",
-                "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166",
-                "shasum": ""
-            },
-            "require": {
-                "lib-pcre": "*",
-                "php": ">=5.4.0"
-            },
-            "require-dev": {
-                "cebe/indent": "*",
-                "facebook/xhprof": "*@dev",
-                "phpunit/phpunit": "4.1.*"
-            },
-            "bin": [
-                "bin/markdown"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "cebe\\markdown\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Carsten Brandt",
-                    "email": "mail@cebe.cc",
-                    "homepage": "http://cebe.cc/",
-                    "role": "Creator"
-                }
-            ],
-            "description": "A super fast, highly extensible markdown parser for PHP",
-            "homepage": "https://github.com/cebe/markdown#readme",
-            "keywords": [
-                "extensible",
-                "fast",
-                "gfm",
-                "markdown",
-                "markdown-extra"
-            ],
-            "time": "2016-09-14 20:40:20"
-        },
-        {
-            "name": "ezyang/htmlpurifier",
-            "version": "v4.8.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/ezyang/htmlpurifier.git",
-                "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2",
-                "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "HTMLPurifier": "library/"
-                },
-                "files": [
-                    "library/HTMLPurifier.composer.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL"
-            ],
-            "authors": [
-                {
-                    "name": "Edward Z. Yang",
-                    "email": "admin@htmlpurifier.org",
-                    "homepage": "http://ezyang.com"
-                }
-            ],
-            "description": "Standards compliant HTML filter written in PHP",
-            "homepage": "http://htmlpurifier.org/",
-            "keywords": [
-                "html"
-            ],
-            "time": "2016-07-16 12:58:58"
-        },
-        {
-            "name": "yiisoft/yii2",
-            "version": "2.0.10",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/yiisoft/yii2-framework.git",
-                "reference": "5bfcb7a6dfa9771e2248eb8c4448613330f343ff"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/5bfcb7a6dfa9771e2248eb8c4448613330f343ff",
-                "reference": "5bfcb7a6dfa9771e2248eb8c4448613330f343ff",
-                "shasum": ""
-            },
-            "require": {
-                "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
-                "bower-asset/jquery.inputmask": "~3.2.2",
-                "bower-asset/punycode": "1.3.*",
-                "bower-asset/yii2-pjax": "~2.0.1",
-                "cebe/markdown": "~1.0.0 | ~1.1.0",
-                "ext-ctype": "*",
-                "ext-mbstring": "*",
-                "ezyang/htmlpurifier": "~4.6",
-                "lib-pcre": "*",
-                "php": ">=5.4.0",
-                "yiisoft/yii2-composer": "~2.0.4"
-            },
-            "bin": [
-                "yii"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "yii\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Qiang Xue",
-                    "email": "qiang.xue@gmail.com",
-                    "homepage": "http://www.yiiframework.com/",
-                    "role": "Founder and project lead"
-                },
-                {
-                    "name": "Alexander Makarov",
-                    "email": "sam@rmcreative.ru",
-                    "homepage": "http://rmcreative.ru/",
-                    "role": "Core framework development"
-                },
-                {
-                    "name": "Maurizio Domba",
-                    "homepage": "http://mdomba.info/",
-                    "role": "Core framework development"
-                },
-                {
-                    "name": "Carsten Brandt",
-                    "email": "mail@cebe.cc",
-                    "homepage": "http://cebe.cc/",
-                    "role": "Core framework development"
-                },
-                {
-                    "name": "Timur Ruziev",
-                    "email": "resurtm@gmail.com",
-                    "homepage": "http://resurtm.com/",
-                    "role": "Core framework development"
-                },
-                {
-                    "name": "Paul Klimov",
-                    "email": "klimov.paul@gmail.com",
-                    "role": "Core framework development"
-                },
-                {
-                    "name": "Dmitry Naumenko",
-                    "email": "d.naumenko.a@gmail.com",
-                    "role": "Core framework development"
-                }
-            ],
-            "description": "Yii PHP Framework Version 2",
-            "homepage": "http://www.yiiframework.com/",
-            "keywords": [
-                "framework",
-                "yii2"
-            ],
-            "time": "2016-10-20 12:02:50"
-        },
-        {
-            "name": "yiisoft/yii2-composer",
-            "version": "2.0.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/yiisoft/yii2-composer.git",
-                "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/7452fd908a5023b8bb5ea1b123a174ca080de464",
-                "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464",
-                "shasum": ""
-            },
-            "require": {
-                "composer-plugin-api": "^1.0"
-            },
-            "type": "composer-plugin",
-            "extra": {
-                "class": "yii\\composer\\Plugin",
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "yii\\composer\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Qiang Xue",
-                    "email": "qiang.xue@gmail.com"
-                }
-            ],
-            "description": "The composer plugin for Yii extension installer",
-            "keywords": [
-                "composer",
-                "extension installer",
-                "yii2"
-            ],
-            "time": "2016-02-06 00:49:24"
-        }
-    ],
-    "packages-dev": [
-        {
-            "name": "doctrine/instantiator",
-            "version": "1.0.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/instantiator.git",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3,<8.0-DEV"
-            },
-            "require-dev": {
-                "athletic/athletic": "~0.1.8",
-                "ext-pdo": "*",
-                "ext-phar": "*",
-                "phpunit/phpunit": "~4.0",
-                "squizlabs/php_codesniffer": "~2.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Marco Pivetta",
-                    "email": "ocramius@gmail.com",
-                    "homepage": "http://ocramius.github.com/"
-                }
-            ],
-            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
-            "homepage": "https://github.com/doctrine/instantiator",
-            "keywords": [
-                "constructor",
-                "instantiate"
-            ],
-            "time": "2015-06-14 21:17:01"
-        },
-        {
-            "name": "myclabs/deep-copy",
-            "version": "1.5.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/myclabs/DeepCopy.git",
-                "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108",
-                "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.4.0"
-            },
-            "require-dev": {
-                "doctrine/collections": "1.*",
-                "phpunit/phpunit": "~4.1"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "DeepCopy\\": "src/DeepCopy/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "description": "Create deep copies (clones) of your objects",
-            "homepage": "https://github.com/myclabs/DeepCopy",
-            "keywords": [
-                "clone",
-                "copy",
-                "duplicate",
-                "object",
-                "object graph"
-            ],
-            "time": "2016-10-31 17:19:45"
-        },
-        {
-            "name": "phpdocumentor/reflection-common",
-            "version": "1.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
-                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
-                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.6"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jaap van Otterdijk",
-                    "email": "opensource@ijaap.nl"
-                }
-            ],
-            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
-            "homepage": "http://www.phpdoc.org",
-            "keywords": [
-                "FQSEN",
-                "phpDocumentor",
-                "phpdoc",
-                "reflection",
-                "static analysis"
-            ],
-            "time": "2015-12-27 11:43:31"
-        },
-        {
-            "name": "phpdocumentor/reflection-docblock",
-            "version": "3.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
-                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
-                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5",
-                "phpdocumentor/reflection-common": "^1.0@dev",
-                "phpdocumentor/type-resolver": "^0.2.0",
-                "webmozart/assert": "^1.0"
-            },
-            "require-dev": {
-                "mockery/mockery": "^0.9.4",
-                "phpunit/phpunit": "^4.4"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "me@mikevanriel.com"
-                }
-            ],
-            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
-            "time": "2016-09-30 07:12:33"
-        },
-        {
-            "name": "phpdocumentor/type-resolver",
-            "version": "0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/TypeResolver.git",
-                "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443",
-                "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5",
-                "phpdocumentor/reflection-common": "^1.0"
-            },
-            "require-dev": {
-                "mockery/mockery": "^0.9.4",
-                "phpunit/phpunit": "^5.2||^4.8.24"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "me@mikevanriel.com"
-                }
-            ],
-            "time": "2016-06-10 07:14:17"
-        },
-        {
-            "name": "phpspec/prophecy",
-            "version": "v1.6.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "58a8137754bc24b25740d4281399a4a3596058e0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
-                "reference": "58a8137754bc24b25740d4281399a4a3596058e0",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "php": "^5.3|^7.0",
-                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
-                "sebastian/comparator": "^1.1",
-                "sebastian/recursion-context": "^1.0"
-            },
-            "require-dev": {
-                "phpspec/phpspec": "^2.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.6.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Prophecy\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com",
-                    "homepage": "http://everzet.com"
-                },
-                {
-                    "name": "Marcello Duarte",
-                    "email": "marcello.duarte@gmail.com"
-                }
-            ],
-            "description": "Highly opinionated mocking framework for PHP 5.3+",
-            "homepage": "https://github.com/phpspec/prophecy",
-            "keywords": [
-                "Double",
-                "Dummy",
-                "fake",
-                "mock",
-                "spy",
-                "stub"
-            ],
-            "time": "2016-06-07 08:13:47"
-        },
-        {
-            "name": "phpunit/php-code-coverage",
-            "version": "4.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
-                "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.6 || ^7.0",
-                "phpunit/php-file-iterator": "~1.3",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-token-stream": "^1.4.2",
-                "sebastian/code-unit-reverse-lookup": "~1.0",
-                "sebastian/environment": "^1.3.2 || ^2.0",
-                "sebastian/version": "~1.0|~2.0"
-            },
-            "require-dev": {
-                "ext-xdebug": ">=2.1.4",
-                "phpunit/phpunit": "^5.4"
-            },
-            "suggest": {
-                "ext-dom": "*",
-                "ext-xdebug": ">=2.4.0",
-                "ext-xmlwriter": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
-            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
-            "keywords": [
-                "coverage",
-                "testing",
-                "xunit"
-            ],
-            "time": "2016-11-01 05:06:24"
-        },
-        {
-            "name": "phpunit/php-file-iterator",
-            "version": "1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
-                "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
-                "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
-            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
-            "keywords": [
-                "filesystem",
-                "iterator"
-            ],
-            "time": "2015-06-21 13:08:43"
-        },
-        {
-            "name": "phpunit/php-text-template",
-            "version": "1.2.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-text-template.git",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Simple template engine.",
-            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
-            "keywords": [
-                "template"
-            ],
-            "time": "2015-06-21 13:50:34"
-        },
-        {
-            "name": "phpunit/php-timer",
-            "version": "1.0.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-timer.git",
-                "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
-                "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4|~5"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Utility class for timing",
-            "homepage": "https://github.com/sebastianbergmann/php-timer/",
-            "keywords": [
-                "timer"
-            ],
-            "time": "2016-05-12 18:03:57"
-        },
-        {
-            "name": "phpunit/php-token-stream",
-            "version": "1.4.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
-                "shasum": ""
-            },
-            "require": {
-                "ext-tokenizer": "*",
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Wrapper around PHP's tokenizer extension.",
-            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
-            "keywords": [
-                "tokenizer"
-            ],
-            "time": "2015-09-15 10:49:45"
-        },
-        {
-            "name": "phpunit/phpunit",
-            "version": "5.5.7",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3f67cee782c9abfaee5e32fd2f57cdd54bc257ba",
-                "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba",
-                "shasum": ""
-            },
-            "require": {
-                "ext-dom": "*",
-                "ext-json": "*",
-                "ext-libxml": "*",
-                "ext-mbstring": "*",
-                "ext-xml": "*",
-                "myclabs/deep-copy": "~1.3",
-                "php": "^5.6 || ^7.0",
-                "phpspec/prophecy": "^1.3.1",
-                "phpunit/php-code-coverage": "^4.0.1",
-                "phpunit/php-file-iterator": "~1.4",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-timer": "^1.0.6",
-                "phpunit/phpunit-mock-objects": "^3.2",
-                "sebastian/comparator": "~1.1",
-                "sebastian/diff": "~1.2",
-                "sebastian/environment": "^1.3 || ^2.0",
-                "sebastian/exporter": "~1.2",
-                "sebastian/global-state": "~1.0",
-                "sebastian/object-enumerator": "~1.0",
-                "sebastian/resource-operations": "~1.0",
-                "sebastian/version": "~1.0|~2.0",
-                "symfony/yaml": "~2.1|~3.0"
-            },
-            "conflict": {
-                "phpdocumentor/reflection-docblock": "3.0.2"
-            },
-            "require-dev": {
-                "ext-pdo": "*"
-            },
-            "suggest": {
-                "ext-tidy": "*",
-                "ext-xdebug": "*",
-                "phpunit/php-invoker": "~1.1"
-            },
-            "bin": [
-                "phpunit"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "5.5.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "The PHP Unit Testing framework.",
-            "homepage": "https://phpunit.de/",
-            "keywords": [
-                "phpunit",
-                "testing",
-                "xunit"
-            ],
-            "time": "2016-10-03 13:04:15"
-        },
-        {
-            "name": "phpunit/phpunit-mock-objects",
-            "version": "3.4.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
-                "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2",
-                "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "php": "^5.6 || ^7.0",
-                "phpunit/php-text-template": "^1.2",
-                "sebastian/exporter": "^1.2"
-            },
-            "conflict": {
-                "phpunit/phpunit": "<5.4.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^5.4"
-            },
-            "suggest": {
-                "ext-soap": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Mock Object library for PHPUnit",
-            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
-            "keywords": [
-                "mock",
-                "xunit"
-            ],
-            "time": "2016-10-09 07:01:45"
-        },
-        {
-            "name": "sebastian/code-unit-reverse-lookup",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
-                "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
-                "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Looks up which function or method a line of code belongs to",
-            "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
-            "time": "2016-02-13 06:45:14"
-        },
-        {
-            "name": "sebastian/comparator",
-            "version": "1.2.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/diff": "~1.2",
-                "sebastian/exporter": "~1.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides the functionality to compare PHP values for equality",
-            "homepage": "http://www.github.com/sebastianbergmann/comparator",
-            "keywords": [
-                "comparator",
-                "compare",
-                "equality"
-            ],
-            "time": "2015-07-26 15:48:44"
-        },
-        {
-            "name": "sebastian/diff",
-            "version": "1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
-                "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.8"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Kore Nordmann",
-                    "email": "mail@kore-nordmann.de"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Diff implementation",
-            "homepage": "https://github.com/sebastianbergmann/diff",
-            "keywords": [
-                "diff"
-            ],
-            "time": "2015-12-08 07:14:41"
-        },
-        {
-            "name": "sebastian/environment",
-            "version": "1.3.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/environment.git",
-                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
-                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3 || ^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.8 || ^5.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides functionality to handle HHVM/PHP environments",
-            "homepage": "http://www.github.com/sebastianbergmann/environment",
-            "keywords": [
-                "Xdebug",
-                "environment",
-                "hhvm"
-            ],
-            "time": "2016-08-18 05:49:44"
-        },
-        {
-            "name": "sebastian/exporter",
-            "version": "1.2.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
-                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/recursion-context": "~1.0"
-            },
-            "require-dev": {
-                "ext-mbstring": "*",
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides the functionality to export PHP variables for visualization",
-            "homepage": "http://www.github.com/sebastianbergmann/exporter",
-            "keywords": [
-                "export",
-                "exporter"
-            ],
-            "time": "2016-06-17 09:04:28"
-        },
-        {
-            "name": "sebastian/global-state",
-            "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/global-state.git",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "suggest": {
-                "ext-uopz": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Snapshotting of global state",
-            "homepage": "http://www.github.com/sebastianbergmann/global-state",
-            "keywords": [
-                "global state"
-            ],
-            "time": "2015-10-12 03:26:01"
-        },
-        {
-            "name": "sebastian/object-enumerator",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/object-enumerator.git",
-                "reference": "d4ca2fb70344987502567bc50081c03e6192fb26"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26",
-                "reference": "d4ca2fb70344987502567bc50081c03e6192fb26",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6",
-                "sebastian/recursion-context": "~1.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Traverses array structures and object graphs to enumerate all referenced objects",
-            "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
-            "time": "2016-01-28 13:25:10"
-        },
-        {
-            "name": "sebastian/recursion-context",
-            "version": "1.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/recursion-context.git",
-                "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
-                "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides functionality to recursively process PHP variables",
-            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
-            "time": "2015-11-11 19:50:13"
-        },
-        {
-            "name": "sebastian/resource-operations",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/resource-operations.git",
-                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
-                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides a list of PHP built-in functions that operate on resources",
-            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
-            "time": "2015-07-28 20:34:47"
-        },
-        {
-            "name": "sebastian/version",
-            "version": "2.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/version.git",
-                "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5",
-                "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.6"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
-            "homepage": "https://github.com/sebastianbergmann/version",
-            "time": "2016-02-04 12:56:52"
-        },
-        {
-            "name": "symfony/yaml",
-            "version": "v3.1.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/yaml.git",
-                "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27",
-                "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5.9"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.1-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Yaml\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Yaml Component",
-            "homepage": "https://symfony.com",
-            "time": "2016-10-24 18:41:13"
-        },
-        {
-            "name": "webmozart/assert",
-            "version": "1.1.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/webmozart/assert.git",
-                "reference": "bb2d123231c095735130cc8f6d31385a44c7b308"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308",
-                "reference": "bb2d123231c095735130cc8f6d31385a44c7b308",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3|^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.6",
-                "sebastian/version": "^1.0.1"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Webmozart\\Assert\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "Assertions to validate method input/output with nice error messages.",
-            "keywords": [
-                "assert",
-                "check",
-                "validate"
-            ],
-            "time": "2016-08-09 15:02:57"
-        }
-    ],
-    "aliases": [],
-    "minimum-stability": "stable",
-    "stability-flags": [],
-    "prefer-stable": false,
-    "prefer-lowest": false,
-    "platform": [],
-    "platform-dev": []
-}
diff --git a/src/Controller.php b/src/Controller.php
new file mode 100644
index 0000000..7286eba
--- /dev/null
+++ b/src/Controller.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi;
+
+
+use yii\filters\ContentNegotiator;
+use yii\helpers\ArrayHelper;
+use yii\web\Response;
+
+class Controller extends \yii\rest\Controller
+{
+    public $serializer = 'tuyakhov\jsonapi\Serializer';
+
+    /**
+     * @inheritdoc
+     */
+    public function behaviors()
+    {
+        return ArrayHelper::merge(parent::behaviors(), [
+            'contentNegotiator' => [
+                'class' => ContentNegotiator::className(),
+                'formats' => [
+                    'application/vnd.api+json' => Response::FORMAT_JSON,
+                ],
+            ]
+        ]);
+    }
+
+}
\ No newline at end of file
diff --git a/src/Inflector.php b/src/Inflector.php
index cb33a28..469c46c 100644
--- a/src/Inflector.php
+++ b/src/Inflector.php
@@ -30,7 +30,7 @@ public static function var2member($var)
      */
     public static function member2var($member)
     {
-        return str_replace(' ', '_', preg_replace('/[^A-Za-z0-9]+/', ' ', $member));
+        return str_replace(' ', '_', preg_replace('/[^A-Za-z0-9\.]+/', ' ', $member));
     }
 
     /**
diff --git a/src/JsonApiParser.php b/src/JsonApiParser.php
index 730f976..6792165 100644
--- a/src/JsonApiParser.php
+++ b/src/JsonApiParser.php
@@ -34,13 +34,16 @@ class JsonApiParser extends JsonParser
     public function parse($rawBody, $contentType)
     {
         $array = parent::parse($rawBody, $contentType);
-        $data =  ArrayHelper::getValue($array, 'data', []);
-        if (empty($data)) {
+        if (!empty($array) && !ArrayHelper::keyExists('data', $array)) {
             if ($this->throwException) {
                 throw new BadRequestHttpException('The request MUST include a single resource object as primary data.');
             }
             return [];
         }
+        $data =  ArrayHelper::getValue($array, 'data', []);
+        if (empty($data)) {
+            return [];
+        }
         if (ArrayHelper::isAssociative($data)) {
             $result = $this->parseResource($data);
 
@@ -109,12 +112,14 @@ protected function parseRelationships(array $relObjects = [])
     {
         $relationships = [];
         foreach ($relObjects as $name => $relationship) {
-            if (!$relData = ArrayHelper::getValue($relationship, 'data')) {
+            if (!ArrayHelper::keyExists('data', $relationship)) {
                 continue;
             }
+            $relData = ArrayHelper::getValue($relationship, 'data', []);
             if (!ArrayHelper::isIndexed($relData)) {
                 $relData = [$relData];
             }
+            $relationships[$name] = [];
             foreach ($relData as $identifier) {
                 if (isset($identifier['type']) && isset($identifier['id'])) {
                     $formName = $this->typeToFormName($identifier['type']);
diff --git a/src/JsonApiResponseFormatter.php b/src/JsonApiResponseFormatter.php
index 705a454..fb37fd7 100644
--- a/src/JsonApiResponseFormatter.php
+++ b/src/JsonApiResponseFormatter.php
@@ -8,11 +8,31 @@
 use yii\base\Component;
 use yii\helpers\ArrayHelper;
 use yii\helpers\Json;
+use yii\helpers\Url;
+use yii\web\ErrorHandler;
+use yii\web\Link;
 use yii\web\Response;
 use yii\web\ResponseFormatterInterface;
 
 class JsonApiResponseFormatter extends Component implements ResponseFormatterInterface
 {
+    /**
+     * Mapping between the error handler component and JSON API error object
+     * @see ErrorHandler::convertExceptionToArray()
+     */
+    const ERROR_EXCEPTION_MAPPING = [
+        'title' => 'name',
+        'detail' => 'message',
+        'code' => 'code',
+        'status' => 'status'
+    ];
+    /**
+     * An error object MAY have the following members
+     * @link http://jsonapi.org/format/#error-objects
+     */
+    const ERROR_ALLOWED_MEMBERS = [
+        'id', 'links', 'status', 'code', 'title', 'detail', 'source', 'meta'
+    ];
     /**
      * @var integer the encoding options passed to [[Json::encode()]]. For more details please refer to
      * <http://www.php.net/manual/en/function.json-encode.php>.
@@ -34,19 +54,41 @@ class JsonApiResponseFormatter extends Component implements ResponseFormatterInt
     public function format($response)
     {
         $response->getHeaders()->set('Content-Type', 'application/vnd.api+json; charset=UTF-8');
-        if ($response->data !== null) {
-            $options = $this->encodeOptions;
-            if ($this->prettyPrint) {
-                $options |= JSON_PRETTY_PRINT;
+        $options = $this->encodeOptions;
+        if ($this->prettyPrint) {
+            $options |= JSON_PRETTY_PRINT;
+        }
+
+        $apiDocument = $response->data;
+
+        if (!$response->isEmpty && empty($apiDocument)) {
+            $apiDocument = ['data' => $response->data];
+            if (\Yii::$app->controller) {
+                $apiDocument['links'] = Link::serialize([
+                    Link::REL_SELF => Url::current([], true)
+                ]);
             }
-            $apiDocument = $response->data;
-            if ($response->isClientError || $response->isServerError) {
-                if (ArrayHelper::isAssociative($response->data)) {
-                    $response->data = [$response->data];
+        }
+
+        if ($response->isClientError || $response->isServerError) {
+            if (ArrayHelper::isAssociative($response->data)) {
+                $response->data = [$response->data];
+            }
+            $formattedErrors = [];
+            foreach ($response->data as $error) {
+                $formattedError = array_intersect_key($error, array_flip(static::ERROR_ALLOWED_MEMBERS));
+                foreach (static::ERROR_EXCEPTION_MAPPING as $member => $key) {
+                    if (isset($error[$key])) {
+                        $formattedError[$member] = (string) $error[$key];
+                    }
+                }
+                if (!empty($formattedError)) {
+                    $formattedErrors[] = $formattedError;
                 }
-                $apiDocument = ['errors' => $response->data];
             }
-
+            $apiDocument = ['errors' => $formattedErrors];
+        }
+        if ($apiDocument !== null) {
             $response->content = Json::encode($apiDocument, $options);
         }
     }
diff --git a/src/Pagination.php b/src/Pagination.php
new file mode 100644
index 0000000..a277466
--- /dev/null
+++ b/src/Pagination.php
@@ -0,0 +1,37 @@
+<?php
+
+
+namespace tuyakhov\jsonapi;
+
+use Yii;
+use yii\web\Request;
+
+/**
+ * This class enables the `page` query parameter family.
+ * Query parameters such as page[number] and page[size] might be used.
+ * @link https://jsonapi.org/format/1.1/#fetching-pagination
+ */
+class Pagination extends \yii\data\Pagination
+{
+    /** @var string default page size parameter */
+    public $pageSizeParam = 'size';
+
+    /** @var string default page number parameter  */
+    public $pageParam = 'number';
+
+    /**
+     * Support `page` query parameter family
+    */
+    public function init()
+    {
+        if ($this->params === null) {
+            $request = Yii::$app->getRequest();
+            $params = $request instanceof Request ? $request->getQueryParam('page') : [];
+            if (!is_array($params)) {
+                $params = [];
+            }
+            $this->params = $params;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/ResourceInterface.php b/src/ResourceInterface.php
index 6afc163..aeb52fe 100644
--- a/src/ResourceInterface.php
+++ b/src/ResourceInterface.php
@@ -19,10 +19,11 @@ public function getResourceAttributes(array $fields = []);
 
     /**
      * The "relationships" member of the resource object describing relationships between the resource and other JSON API resources.
+     * @param array $linked specific resource linkage that a client has requested.
      * @return ResourceIdentifierInterface[] represent references from the resource object in which it’s defined to other resource objects.
      */
-    public function getResourceRelationships();
+    public function getResourceRelationships(array $linked = []);
 
     public function setResourceRelationship($name, $relationship);
 
-}
+}
\ No newline at end of file
diff --git a/src/ResourceTrait.php b/src/ResourceTrait.php
index 8be89a7..df296e2 100644
--- a/src/ResourceTrait.php
+++ b/src/ResourceTrait.php
@@ -12,6 +12,12 @@
 
 trait ResourceTrait
 {
+    /**
+     * @var bool a flag that enables/disables deleting of the model that contains the foreign key when setting relationships
+     * By default the model's foreign key will be set `null` and saved.
+     */
+    protected $allowDeletingResources = false;
+
     /**
      * @return string
      */
@@ -51,19 +57,26 @@ public function getResourceAttributes(array $fields = [])
     }
 
     /**
+     * @param array $linked
      * @return array
      */
-    public function getResourceRelationships()
+    public function getResourceRelationships(array $linked = [])
     {
-        $relationships = [];
         $fields = [];
         if ($this instanceof Arrayable) {
             $fields = $this->extraFields();
         }
+        $resolvedFields = $this->resolveFields($fields);
+        $keys = array_keys($resolvedFields);
+
+        $relationships = array_fill_keys($keys, null);
+        $linkedFields = array_intersect($keys, $linked);
 
-        foreach ($this->resolveFields($fields) as $name => $definition) {
+        foreach ($linkedFields as $name) {
+            $definition = $resolvedFields[$name];
             $relationships[$name] = is_string($definition) ? $this->$definition : call_user_func($definition, $this, $name);
         }
+
         return $relationships;
     }
 
@@ -80,6 +93,7 @@ public function setResourceRelationship($name, $relationship)
         if (!is_array($relationship)) {
             $relationship = [$relationship];
         }
+        $this->unlinkAll($name, $this->allowDeletingResources);
         foreach ($relationship as $key => $value) {
             if ($value instanceof ActiveRecordInterface) {
                 $this->link($name, $value);
@@ -131,4 +145,20 @@ protected function resolveFields(array $fields, array $fieldSet = [])
 
         return $result;
     }
+
+    /**
+     * @param $value boolean
+     */
+    public function setAllowDeletingResources($value)
+    {
+        $this->allowDeletingResources = $value;
+    }
+
+    /**
+     * @return bool
+     */
+    public function getAllowDeletingResources()
+    {
+        return $this->allowDeletingResources;
+    }
 }
diff --git a/src/Serializer.php b/src/Serializer.php
index 3881173..481f79c 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -102,15 +102,23 @@ public function serialize($data)
     }
 
     /**
+     * @param array $included
      * @param ResourceInterface $model
      * @return array
      */
-    protected function serializeModel(ResourceInterface $model)
+    protected function serializeModel(ResourceInterface $model, array $included = [])
     {
         $fields = $this->getRequestedFields();
         $type = $this->pluralize ? Inflector::pluralize($model->getType()) : $model->getType();
         $fields = isset($fields[$type]) ? $fields[$type] : [];
 
+        $topLevel = array_map(function($item) {
+            if (($pos = strrpos($item, '.')) !== false) {
+                return substr($item, 0, $pos);
+            }
+            return $item;
+        }, $included);
+
         $attributes = $model->getResourceAttributes($fields);
         $attributes = array_combine($this->prepareMemberNames(array_keys($attributes)), array_values($attributes));
 
@@ -118,8 +126,7 @@ protected function serializeModel(ResourceInterface $model)
             'attributes' => $attributes,
         ]);
 
-        $included = $this->getIncluded();
-        $relationships = $model->getResourceRelationships();
+        $relationships = $model->getResourceRelationships($topLevel);
         if (!empty($relationships)) {
             foreach ($relationships as $name => $items) {
                 $relationship = [];
@@ -132,17 +139,15 @@ protected function serializeModel(ResourceInterface $model)
                 } elseif ($items instanceof ResourceIdentifierInterface) {
                     $relationship = $this->serializeIdentifier($items);
                 }
+                $memberName = $this->prepareMemberNames([$name]);
+                $memberName = reset($memberName);
                 if (!empty($relationship)) {
-                    $memberName = $this->prepareMemberNames([$name]);
-                    $memberName = reset($memberName);
-                    if (in_array($name, $included)) {
-                        $data['relationships'][$memberName]['data'] = $relationship;
-                    }
-                    if ($model instanceof LinksInterface) {
-                        $links = $model->getRelationshipLinks($memberName);
-                        if (!empty($links)) {
-                            $data['relationships'][$memberName]['links'] = Link::serialize($links);
-                        }
+                    $data['relationships'][$memberName]['data'] = $relationship;
+                }
+                if ($model instanceof LinksInterface) {
+                    $links = $model->getRelationshipLinks($memberName);
+                    if (!empty($links)) {
+                        $data['relationships'][$memberName]['links'] = Link::serialize($links);
                     }
                 }
             }
@@ -164,11 +169,14 @@ protected function serializeResource(ResourceInterface $resource)
         if ($this->request->getIsHead()) {
             return null;
         } else {
-            $data = ['data' => $this->serializeModel($resource)];
+            $included = $this->getIncluded();
+            $data = [
+                'data' => $this->serializeModel($resource, $included)
+            ];
 
-            $included = $this->serializeIncluded($resource);
-            if (!empty($included)) {
-                $data['included'] = $included;
+            $relatedResources = $this->serializeIncluded($resource, $included);
+            if (!empty($relatedResources)) {
+                $data['included'] = $relatedResources;
             }
 
             return $data;
@@ -200,42 +208,60 @@ protected function serializeIdentifier(ResourceIdentifierInterface $identifier)
 
     /**
      * @param ResourceInterface|array $resources
+     * @param array $included
+     * @param true $assoc
      * @return array
      */
-    protected function serializeIncluded($resources)
+    protected function serializeIncluded($resources, array $included = [], $assoc = false)
     {
-        $included = $this->getIncluded();
         $resources = is_array($resources) ? $resources : [$resources];
         $data = [];
 
+        $inclusion = [];
+        foreach ($included as $path) {
+            if (($pos = strrpos($path, '.')) === false) {
+                $inclusion[$path] = [];
+                continue;
+            }
+            $name = substr($path, $pos + 1);
+            $key = substr($path, 0, $pos);
+            $inclusion[$key][] = $name;
+        }
+
         foreach ($resources as $resource) {
             if (!$resource instanceof  ResourceInterface) {
                 continue;
             }
-            $relationships = $resource->getResourceRelationships();
+            $relationships = $resource->getResourceRelationships(array_keys($inclusion));
             foreach ($relationships as $name => $relationship) {
-                if (!in_array($name, $included)) {
+                if ($relationship === null) {
                     continue;
                 }
                 if (!is_array($relationship)) {
                     $relationship = [$relationship];
                 }
                 foreach ($relationship as $model) {
-                    if ($model instanceof ResourceInterface) {
-                        $uniqueKey = $model->getType() . '/' . $model->getId();
-                        $data[$uniqueKey] = $this->serializeModel($model);
+                    if (!$model instanceof ResourceInterface) {
+                        continue;
+                    }
+                    $uniqueKey = $model->getType() . '/' . $model->getId();
+                    if (!isset($data[$uniqueKey])) {
+                        $data[$uniqueKey] = $this->serializeModel($model, $inclusion[$name]);
+                    }
+                    if (!empty($inclusion[$name])) {
+                        $data = array_merge($data, $this->serializeIncluded($model, $inclusion[$name], true));
                     }
                 }
             }
         }
 
-        return array_values($data);
+        return $assoc ? $data : array_values($data);
     }
 
     /**
      * Serializes a data provider.
      * @param DataProviderInterface $dataProvider
-     * @return array the array representation of the data provider.
+     * @return null|array the array representation of the data provider.
      */
     protected function serializeDataProvider($dataProvider)
     {
@@ -245,17 +271,18 @@ protected function serializeDataProvider($dataProvider)
             $models = $dataProvider->getModels();
             $data = [];
 
+            $included = $this->getIncluded();
             foreach ($models as $model) {
                 if ($model instanceof ResourceInterface) {
-                    $data[] = $this->serializeModel($model);
+                    $data[] = $this->serializeModel($model, $included);
                 }
             }
 
             $result = ['data' => $data];
 
-            $included = $this->serializeIncluded($models);
-            if (!empty($included)) {
-                $result['included'] = $included;
+            $relatedResources = $this->serializeIncluded($models, $included);
+            if (!empty($relatedResources)) {
+                $result['included'] = $relatedResources;
             }
 
             if (($pagination = $dataProvider->getPagination()) !== false) {
@@ -295,9 +322,11 @@ protected function serializeModelErrors($model)
         $this->response->setStatusCode(422, 'Data Validation Failed.');
         $result = [];
         foreach ($model->getFirstErrors() as $name => $message) {
+            $memberName = call_user_func($this->prepareMemberName, $name);
             $result[] = [
-                'source' => ['pointer' => "/data/attributes/{$name}"],
+                'source' => ['pointer' => "/data/attributes/{$memberName}"],
                 'detail' => $message,
+                'status' => '422'
             ];
         }
 
@@ -320,6 +349,9 @@ protected function getRequestedFields()
         return $fields;
     }
 
+    /**
+     * @return array|null
+     */
     protected function getIncluded()
     {
         $include = $this->request->get($this->expandParam);
diff --git a/src/UrlRule.php b/src/UrlRule.php
new file mode 100644
index 0000000..a5206fd
--- /dev/null
+++ b/src/UrlRule.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi;
+
+
+/**
+ * UrlRule is provided to simplify the creation of URL rules for JSON API support.
+ * @package tuyakhov\jsonapi
+ */
+class UrlRule extends \yii\rest\UrlRule
+{
+    /**
+     * @inheritdoc
+     */
+    public function init()
+    {
+        $this->tokens = array_merge($this->tokens, array_merge([
+            '{relationship}' => '<name:\w+>'
+        ]));
+        $this->patterns = array_merge($this->patterns, [
+            'DELETE {id}/relationships/{relationship}' => 'delete-relationship',
+            'POST,PATCH {id}/relationships/{relationship}' => 'update-relationship',
+            'GET {id}/{relationship}' => 'view-related',
+            '{id}/{relationship}' => 'options'
+        ]);
+        parent::init();
+    }
+
+}
\ No newline at end of file
diff --git a/src/actions/Action.php b/src/actions/Action.php
index 202f69d..27eb2a8 100644
--- a/src/actions/Action.php
+++ b/src/actions/Action.php
@@ -6,6 +6,7 @@
 namespace tuyakhov\jsonapi\actions;
 
 use tuyakhov\jsonapi\ResourceInterface;
+use tuyakhov\jsonapi\ResourceTrait;
 use yii\db\ActiveRecordInterface;
 use yii\db\BaseActiveRecord;
 use yii\helpers\ArrayHelper;
@@ -23,10 +24,15 @@ class Action extends \yii\rest\Action
      */
     public $allowFullReplacement = true;
 
+    /**
+     * @var bool Weather allow to delete the underlying resource if a relationship is deleted (as a garbage collection measure)
+     */
+    public $enableResourceDeleting = false;
+
     /**
      * Links the relationships with primary model.
      * @param $model ActiveRecordInterface
-     * @param array $data
+     * @param array $data relationship links
      */
     protected function linkRelationships($model, array $data = [])
     {
@@ -55,14 +61,16 @@ protected function linkRelationships($model, array $data = [])
                 $ids[] = $relObject['id'];
             }
 
-            if (!$records = $relatedClass::find()->andWhere(['in', $relatedClass::primaryKey(), $ids])->all()) {
+            if ($related->multiple && !$this->allowFullReplacement) {
                 continue;
             }
+            $records = $relatedClass::find()->andWhere(['in', $relatedClass::primaryKey(), $ids])->all();
 
-            if ($related->multiple && !$this->allowFullReplacement) {
-                continue;
+            /** @see ResourceTrait::$allowDeletingResources */
+            if (method_exists($model, 'setAllowDeletingResources')) {
+                $model->setAllowDeletingResources($this->enableResourceDeleting);
             }
-            $model->unlinkAll($name);
+
             $model->setResourceRelationship($name, $records);
         }
     }
diff --git a/src/actions/DeleteAction.php b/src/actions/DeleteAction.php
new file mode 100644
index 0000000..c49d941
--- /dev/null
+++ b/src/actions/DeleteAction.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\actions;
+
+use Yii;
+use yii\db\BaseActiveRecord;
+use yii\web\NotFoundHttpException;
+use yii\web\ServerErrorHttpException;
+
+/**
+ * Implements the API endpoint for deleting resources.
+ * @link http://jsonapi.org/format/#crud-deleting
+ */
+class DeleteAction extends Action
+{
+    /**
+     * Deletes a resource.
+     * @param mixed $id id of the resource to be deleted.
+     * @throws NotFoundHttpException
+     * @throws ServerErrorHttpException on failure.
+     */
+    public function run($id)
+    {
+        /** @var BaseActiveRecord $model */
+        $model = $this->findModel($id);
+
+        if ($this->checkAccess) {
+            call_user_func($this->checkAccess, $this->id, $model);
+        }
+
+        if ($model->delete() === false) {
+            throw new ServerErrorHttpException('Failed to delete the resource for unknown reason.');
+        }
+
+        Yii::$app->getResponse()->setStatusCode(204);
+    }
+}
\ No newline at end of file
diff --git a/src/actions/DeleteRelationshipAction.php b/src/actions/DeleteRelationshipAction.php
new file mode 100644
index 0000000..96bb3ee
--- /dev/null
+++ b/src/actions/DeleteRelationshipAction.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\actions;
+
+use Yii;
+use yii\data\ActiveDataProvider;
+use yii\db\ActiveRecordInterface;
+use yii\db\ActiveRelationTrait;
+use yii\db\BaseActiveRecord;
+use yii\helpers\ArrayHelper;
+use yii\web\ForbiddenHttpException;
+use yii\web\NotFoundHttpException;
+
+/**
+ * Deletes the specified members from a relationship
+ * @link http://jsonapi.org/format/#crud-updating-relationships
+ */
+class DeleteRelationshipAction extends Action
+{
+    /**
+     * Removes the relationships from primary model.
+     * @var callable
+     */
+    public $unlinkRelationships;
+
+    /**
+     * @param string $id an ID of the primary resource
+     * @param string $name a name of the related resource
+     * @return ActiveDataProvider
+     * @throws ForbiddenHttpException
+     * @throws NotFoundHttpException
+     * @throws \yii\base\InvalidConfigException
+     */
+    public function run($id, $name)
+    {
+        /** @var BaseActiveRecord $model */
+        $model = $this->findModel($id);
+
+        if (!$related = $model->getRelation($name, false)) {
+            throw new NotFoundHttpException('Relationship does not exist');
+        }
+
+        if (!$related->multiple) {
+            throw new ForbiddenHttpException('Unsupported request to update relationship');
+        }
+
+        if ($this->checkAccess) {
+            call_user_func($this->checkAccess, $this->id, $model, $name);
+        }
+
+        $this->unlinkRelationships($model, [$name => Yii::$app->getRequest()->getBodyParams()]);
+
+
+        return new ActiveDataProvider([
+            'query' => $related
+        ]);
+    }
+
+    /**
+     * Removes the relationships from primary model.
+     * @param $model ActiveRecordInterface
+     * @param array $data relationship links
+     */
+    protected function unlinkRelationships($model, array $data = [])
+    {
+        if ($this->unlinkRelationships !== null) {
+            call_user_func($this->unlinkRelationships, $this, $model, $data);
+            return;
+        }
+
+        foreach ($data as $name => $relationship) {
+            /** @var $related ActiveRelationTrait */
+            if (!$related = $model->getRelation($name, false)) {
+                continue;
+            }
+            /** @var BaseActiveRecord $relatedClass */
+            $relatedClass = new $related->modelClass;
+            $relationships = ArrayHelper::keyExists($relatedClass->formName(), $relationship) ? $relationship[$relatedClass->formName()] : [];
+
+            $ids = [];
+            foreach ($relationships as $index => $relObject) {
+                if (!isset($relObject['id'])) {
+                    continue;
+                }
+                $ids[] = $relObject['id'];
+            }
+
+            $records = $relatedClass::find()->andWhere(['in', $relatedClass::primaryKey(), $ids])->all();
+            foreach ($records as $record) {
+                $model->unlink($name, $record, $this->enableResourceDeleting);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/actions/IndexAction.php b/src/actions/IndexAction.php
new file mode 100644
index 0000000..85be334
--- /dev/null
+++ b/src/actions/IndexAction.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\actions;
+
+
+use tuyakhov\jsonapi\Inflector;
+use tuyakhov\jsonapi\Pagination;
+use yii\data\ActiveDataProvider;
+use yii\data\DataFilter;
+use Yii;
+
+class IndexAction extends Action
+{
+    /**
+     * @var callable a PHP callable that will be called to prepare a data provider that
+     * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead.
+     * The signature of the callable should be:
+     *
+     * ```php
+     * function (IndexAction $action) {
+     *     // $action is the action object currently running
+     * }
+     * ```
+     *
+     * The callable should return an instance of [[ActiveDataProvider]].
+     *
+     * If [[dataFilter]] is set the result of [[DataFilter::build()]] will be passed to the callable as a second parameter.
+     * In this case the signature of the callable should be the following:
+     *
+     * ```php
+     * function (IndexAction $action, mixed $filter) {
+     *     // $action is the action object currently running
+     *     // $filter the built filter condition
+     * }
+     * ```
+     */
+    public $prepareDataProvider;
+    /**
+     * @var DataFilter|null data filter to be used for the search filter composition.
+     * You must setup this field explicitly in order to enable filter processing.
+     * For example:
+     *
+     * ```php
+     * [
+     *     'class' => 'yii\data\ActiveDataFilter',
+     *     'searchModel' => function () {
+     *         return (new \yii\base\DynamicModel(['id' => null, 'name' => null, 'price' => null]))
+     *             ->addRule('id', 'integer')
+     *             ->addRule('name', 'trim')
+     *             ->addRule('name', 'string')
+     *             ->addRule('price', 'number');
+     *     },
+     * ]
+     * ```
+     *
+     * @see DataFilter
+     *
+     * @since 2.0.13
+     */
+    public $dataFilter;
+
+
+    /**
+     * @return ActiveDataProvider
+     * @throws \yii\base\InvalidConfigException
+     */
+    public function run()
+    {
+        if ($this->checkAccess) {
+            call_user_func($this->checkAccess, $this->id);
+        }
+
+        return $this->prepareDataProvider();
+    }
+
+    /**
+     * Prepares the data provider that should return the requested collection of the models.
+     * @return mixed|null|object|DataFilter|ActiveDataProvider
+     * @throws \yii\base\InvalidConfigException
+     */
+    protected function prepareDataProvider()
+    {
+        $filter = $this->getFilter();
+
+        if ($this->prepareDataProvider !== null) {
+            return call_user_func($this->prepareDataProvider, $this, $filter);
+        }
+
+        /* @var $modelClass \yii\db\BaseActiveRecord */
+        $modelClass = $this->modelClass;
+
+        $query = $modelClass::find();
+        if (!empty($filter)) {
+            $query->andWhere($filter);
+        }
+
+        return Yii::createObject([
+            'class' => ActiveDataProvider::className(),
+            'query' => $query,
+            'pagination' => [
+                'class' => Pagination::className(),
+            ],
+            'sort' => [
+                'enableMultiSort' => true
+            ]
+        ]);
+    }
+
+    protected function getFilter()
+    {
+        if ($this->dataFilter === null) {
+            return null;
+        }
+        $requestParams = Yii::$app->getRequest()->getQueryParam('filter', []);
+        $attributeMap = [];
+        foreach ($requestParams as $attribute => $value) {
+            $attributeMap[$attribute] = Inflector::camel2id(Inflector::variablize($attribute), '_');
+            if (is_string($value) && strpos($value, ',') !== false) {
+                $requestParams[$attribute] = ['in' => explode(',', $value)];
+            }
+        }
+        $config = array_merge(['attributeMap' => $attributeMap], $this->dataFilter);
+        /** @var DataFilter $dataFilter */
+        $dataFilter = Yii::createObject($config);
+        if ($dataFilter->load(['filter' => $requestParams])) {
+            return $dataFilter->build();
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/src/actions/UpdateRelationshipAction.php b/src/actions/UpdateRelationshipAction.php
index 218ebe3..54deb24 100644
--- a/src/actions/UpdateRelationshipAction.php
+++ b/src/actions/UpdateRelationshipAction.php
@@ -5,7 +5,6 @@
 
 namespace tuyakhov\jsonapi\actions;
 
-use tuyakhov\jsonapi\ResourceInterface;
 use yii\data\ActiveDataProvider;
 use yii\db\BaseActiveRecord;
 use yii\web\BadRequestHttpException;
diff --git a/src/actions/ViewAction.php b/src/actions/ViewAction.php
new file mode 100644
index 0000000..1570dfe
--- /dev/null
+++ b/src/actions/ViewAction.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\actions;
+
+
+class ViewAction extends \yii\rest\ViewAction
+{
+
+}
\ No newline at end of file
diff --git a/src/actions/ViewRelatedAction.php b/src/actions/ViewRelatedAction.php
index 9810071..8fbcf01 100644
--- a/src/actions/ViewRelatedAction.php
+++ b/src/actions/ViewRelatedAction.php
@@ -6,6 +6,7 @@
 namespace tuyakhov\jsonapi\actions;
 
 
+use tuyakhov\jsonapi\Pagination;
 use tuyakhov\jsonapi\ResourceInterface;
 use yii\data\ActiveDataProvider;
 use yii\db\ActiveQuery;
@@ -45,15 +46,18 @@ public function run($id, $name)
         }
 
         if ($this->prepareDataProvider !== null) {
-            return call_user_func($this->prepareDataProvider, $this, $related);
+            return call_user_func($this->prepareDataProvider, $this, $related, $name);
         }
 
         if ($related->multiple) {
             return new ActiveDataProvider([
-                'query' => $related
+                'query' => $related,
+                'pagination' => [
+                    'class' => Pagination::className(),
+                ],
             ]);
         } else {
             return $related->one();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/JsonApiParserTest.php b/tests/JsonApiParserTest.php
index 1a21816..d442273 100644
--- a/tests/JsonApiParserTest.php
+++ b/tests/JsonApiParserTest.php
@@ -8,9 +8,25 @@
 
 use tuyakhov\jsonapi\JsonApiParser;
 use yii\helpers\Json;
+use yii\web\BadRequestHttpException;
 
 class JsonApiParserTest extends TestCase
 {
+    public function testEmptyBody()
+    {
+        $parser = new JsonApiParser();
+        $body = '';
+        $this->assertEquals([], $parser->parse($body, ''));
+    }
+
+    public function testMissingData()
+    {
+        $parser = new JsonApiParser();
+        $this->expectException(BadRequestHttpException::class);
+        $body = Json::encode(['incorrect-member']);
+        $parser->parse($body, '');
+    }
+
     public function testSingleResource()
     {
         $parser = new JsonApiParser();
diff --git a/tests/JsonApiResponseFormatterTest.php b/tests/JsonApiResponseFormatterTest.php
new file mode 100644
index 0000000..3e0e89a
--- /dev/null
+++ b/tests/JsonApiResponseFormatterTest.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+namespace tuyakhov\jsonapi\tests;
+
+
+use tuyakhov\jsonapi\JsonApiResponseFormatter;
+use tuyakhov\jsonapi\Serializer;
+use tuyakhov\jsonapi\tests\data\ResourceModel;
+use yii\base\Controller;
+use yii\helpers\Json;
+use yii\web\Response;
+use yii\web\ServerErrorHttpException;
+
+class JsonApiResponseFormatterTest extends TestCase
+{
+    public function testFormatException()
+    {
+        $formatter = new JsonApiResponseFormatter();
+        $exception = new ServerErrorHttpException('Server error');
+        $response = new Response();
+        $response->setStatusCode($exception->statusCode);
+        $response->data = [
+            'name' => $exception->getName(),
+            'message' => $exception->getMessage(),
+            'code' => $exception->getCode(),
+            'status' => $exception->statusCode
+        ];
+        $formatter->format($response);
+        $this->assertJson($response->content);
+        $this->assertSame(Json::encode([
+            'errors' => [
+                [
+                    'code' => '0',
+                    'status' => '500',
+                    'title' => Response::$httpStatuses[500],
+                    'detail' => 'Server error',
+                ]
+            ]
+        ]), $response->content);
+    }
+
+    public function testFormModelError()
+    {
+        $formatter = new JsonApiResponseFormatter();
+        $exception = new ServerErrorHttpException('Server error');
+        $response = new Response();
+        $response->setStatusCode($exception->statusCode);
+        $serializer = new Serializer();
+        $model = new ResourceModel();
+        $model->addError('field1', 'Error');
+        $model->addError('field2', 'Test Error');
+        $response->data = $serializer->serialize($model);
+        $formatter->format($response);
+        $this->assertJson($response->content);
+        $this->assertSame(Json::encode([
+            'errors' => [
+                [
+                    'source' => ['pointer' => "/data/attributes/field1"],
+                    'detail' => 'Error',
+                    'status' => '422'
+                ],
+                [
+                    'source' => ['pointer' => "/data/attributes/field2"],
+                    'detail' => 'Test Error',
+                    'status' => '422'
+                ]
+            ]
+        ]), $response->content);
+    }
+
+    public function testSuccessModel()
+    {
+        $formatter = new JsonApiResponseFormatter();
+        $response = new Response();
+        $serializer = new Serializer();
+        $model = new ResourceModel();
+        $response->data = $serializer->serialize($model);
+        $response->setStatusCode(200);
+        $formatter->format($response);
+        $this->assertJson($response->content);
+        $this->assertSame(Json::encode([
+            'data' => [
+                'id' => '123',
+                'type' => 'resource-models',
+                'attributes' => [
+                    'field1' => 'test',
+                    'field2' => 2,
+                ],
+                'links' => [
+                    'self' => [
+                        'href' => 'http://example.com/resource/123'
+                    ]
+                ]
+            ]
+        ]), $response->content);
+    }
+
+    public function testEmptyData()
+    {
+        $formatter = new JsonApiResponseFormatter();
+        $response = new Response();
+        $response->setStatusCode('200');
+        $serializer = new Serializer();
+        $response->data = $serializer->serialize(null);
+        $formatter->format($response);
+        $this->assertJson($response->content);
+        $this->assertSame(Json::encode([
+            'data' => null
+        ]), $response->content);
+        \Yii::$app->controller = new Controller('test', \Yii::$app);
+        $formatter->format($response);
+        $this->assertJson($response->content);
+        $this->assertSame(Json::encode([
+            'data' => null,
+            'links' => [
+                'self' => ['href' => '/index.php?r=test']
+            ]
+        ]), $response->content);
+        $response->clear();
+        $response->setStatusCode(201);
+        $formatter->format($response);
+        $this->assertNull($response->content);
+    }
+}
\ No newline at end of file
diff --git a/tests/SerializerTest.php b/tests/SerializerTest.php
index b75c760..eba491d 100644
--- a/tests/SerializerTest.php
+++ b/tests/SerializerTest.php
@@ -35,14 +35,22 @@ public function testSerializeModelErrors()
         $model->addError('field1', 'Test error');
         $model->addError('field2', 'Multiple error 1');
         $model->addError('field2', 'Multiple error 2');
+        $model->addError('first_name', 'Member name check');
         $this->assertEquals([
             [
                 'source' => ['pointer' => "/data/attributes/field1"],
                 'detail' => 'Test error',
+                'status' => '422'
             ],
             [
                 'source' => ['pointer' => "/data/attributes/field2"],
                 'detail' => 'Multiple error 1',
+                'status' => '422'
+            ],
+            [
+                'source' => ['pointer' => "/data/attributes/first-name"],
+                'detail' => 'Member name check',
+                'status' => '422'
             ]
         ], $serializer->serialize($model));
     }
@@ -67,19 +75,39 @@ public function testSerializeModelData()
         ], $serializer->serialize($model));
 
         ResourceModel::$fields = ['first_name'];
-        ResourceModel::$extraFields = [];
-        $this->assertSame([
-            'data' => [
-                'id' => '123',
-                'type' => 'resource-models',
-                'attributes' => [
-                    'first-name' => 'Bob',
-                ],
-                'links' => [
-                    'self' => ['href' => 'http://example.com/resource/123']
+        ResourceModel::$extraFields = ['extraField1'];
+        $model->extraField1 = new ResourceModel();
+        $relationship = [
+            'data' => ['id' => '123', 'type' => 'resource-models'],
+            'links' => [
+                'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
+                'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+            ]
+        ];
+        $resource = [
+            'id' => '123',
+            'type' => 'resource-models',
+            'attributes' => [
+                'first-name' => 'Bob',
+            ],
+            'relationships' => [
+                'extra-field1' => [
+                    'links' => $relationship['links']
                 ]
+            ],
+            'links' => [
+                'self' => ['href' => 'http://example.com/resource/123']
             ]
-        ], $serializer->serialize($model));
+        ];
+        $expected = [
+            'data' => $resource
+        ];
+        $this->assertSame($expected, $serializer->serialize($model));
+        $_POST[$serializer->request->methodParam] = 'POST';
+        \Yii::$app->request->setQueryParams(['include' => 'extra-field1']);
+        $expected['included'][] = $resource;
+        $expected['data']['relationships']['extra-field1'] = $relationship;
+        $this->assertSame($expected, $serializer->serialize($model));
     }
 
     public function testExpand()
@@ -92,16 +120,17 @@ public function testExpand()
                 'field1' => 'test',
                 'field2' => 2,
             ],
-        ];
-        $compoundModel['relationships'] = [
-            'extra-field1' => [
-                'data' => ['id' => '123', 'type' => 'resource-models'],
-                'links' => [
-                    'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
-                    'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+            'relationships' => [
+                'extra-field1' => [
+                    'data' => ['id' => '123', 'type' => 'resource-models'],
+                    'links' => [
+                        'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
+                        'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+                    ]
                 ]
             ]
         ];
+        unset($includedModel['relationships']['extra-field1']['data']);
         $compoundModel['links'] = $includedModel['links'] = [
             'self' => ['href' => 'http://example.com/resource/123']
         ];
@@ -140,6 +169,70 @@ public function testExpand()
         ], $serializer->serialize($model));
     }
 
+    public function testNestedRelationships()
+    {
+        ResourceModel::$fields = ['field1'];
+        ResourceModel::$extraFields = ['extraField1'];
+        $resource = new ResourceModel();
+        $relationship = new ResourceModel();
+        $subRelationship = new ResourceModel();
+        $subRelationship->setId(321);
+        $relationship->extraField1 = $subRelationship;
+        $resource->extraField1 = $relationship;
+        $compoundDocument = [
+            'data' => [
+                'id' => '123',
+                'type' => 'resource-models',
+                'attributes' => ['field1' => 'test'],
+                'relationships' => [
+                    'extra-field1' => [
+                        'data' => ['id' => '123', 'type' => 'resource-models'],
+                        'links' => [
+                            'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
+                            'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+                        ]
+                    ],
+                ],
+                'links' => ['self' => ['href' => 'http://example.com/resource/123']],
+            ],
+            'included' => [
+                [
+                    'id' => '123',
+                    'type' => 'resource-models',
+                    'attributes' => ['field1' => 'test'],
+                    'relationships' => [
+                        'extra-field1' => [
+                            'data' => ['id' => '321', 'type' => 'resource-models'],
+                            'links' => [
+                                'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
+                                'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+                            ]
+                        ],
+                    ],
+                    'links' => ['self' => ['href' => 'http://example.com/resource/123']],
+                ],
+                [
+                    'id' => '321',
+                    'type' => 'resource-models',
+                    'attributes' => ['field1' => 'test'],
+                    'relationships' => [
+                        'extra-field1' => [
+                            'links' => [
+                                'self' => ['href' => 'http://example.com/resource/321/relationships/extra-field1'],
+                                'related' => ['href' => 'http://example.com/resource/321/extra-field1'],
+                            ]
+                        ],
+                    ],
+                    'links' => ['self' => ['href' => 'http://example.com/resource/321']],
+                ]
+            ]
+        ];
+
+        $serializer = new Serializer();
+        \Yii::$app->request->setQueryParams(['include' => 'extra-field1.extra-field1']);
+        $this->assertSame($compoundDocument, $serializer->serialize($resource));
+    }
+
     public function testIncludedDuplicates()
     {
         $serializer = new Serializer();
@@ -151,23 +244,25 @@ public function testIncludedDuplicates()
                 'field1' => 'test',
                 'field2' => 2,
             ],
-        ];
-        $compoundModel['relationships'] = [
-            'extra-field1' => [
-                'data' => ['id' => '123', 'type' => 'resource-models'],
-                'links' => [
-                    'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
-                    'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
-                ]
-            ],
-            'extra-field2' => [
-                'data' => ['id' => '123', 'type' => 'resource-models'],
-                'links' => [
-                    'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field2'],
-                    'related' => ['href' => 'http://example.com/resource/123/extra-field2'],
+            'relationships' => [
+                'extra-field1' => [
+                    'data' => ['id' => '123', 'type' => 'resource-models'],
+                    'links' => [
+                        'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field1'],
+                        'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
+                    ]
+                ],
+                'extra-field2' => [
+                    'data' => ['id' => '123', 'type' => 'resource-models'],
+                    'links' => [
+                        'self' => ['href' => 'http://example.com/resource/123/relationships/extra-field2'],
+                        'related' => ['href' => 'http://example.com/resource/123/extra-field2'],
+                    ]
                 ]
             ]
         ];
+        unset($includedModel['relationships']['extra-field1']['data']);
+        unset($includedModel['relationships']['extra-field2']['data']);
         $compoundModel['links'] = $includedModel['links'] = [
             'self' => ['href' => 'http://example.com/resource/123']
         ];
@@ -175,10 +270,12 @@ public function testIncludedDuplicates()
         $model = new ResourceModel();
         ResourceModel::$fields = ['field1', 'field2'];
         ResourceModel::$extraFields = ['extraField1', 'extraField2'];
+        $relationship = new ResourceModel();
+        $relationship->extraField1 = new ResourceModel();
+        $model->extraField2 = $relationship;
         $model->extraField1 = new ResourceModel();
-        $model->extraField2 = new ResourceModel();
 
-        \Yii::$app->request->setQueryParams(['include' => 'extra-field1,extra-field2']);
+        \Yii::$app->request->setQueryParams(['include' => 'extra-field1,extra-field2.extra-field1']);
         $this->assertSame([
             'data' => $compoundModel,
             'included' => [
@@ -191,7 +288,7 @@ public function testIncludedDuplicates()
                 $includedModel
             ],
             'links' => [
-                'self' => ['href' => '/index.php?r=&include=extra-field1%2Cextra-field2&page=1']
+                'self' => ['href' => '/index.php?r=&include=extra-field1%2Cextra-field2.extra-field1&page=1']
             ],
             'meta' => [
                 'total-count' => 1,
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 6ed1c5e..4b5711f 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -5,6 +5,7 @@
 namespace tuyakhov\jsonapi\tests;
 
 use \yii\helpers\ArrayHelper;
+use yii\web\Response;
 
 class TestCase extends \PHPUnit_Framework_TestCase
 {
@@ -37,6 +38,12 @@ protected function mockApplication($config = [], $appClass = '\yii\web\Applicati
                     'cookieValidationKey' => 'wefJDF8sfdsfSDefwqdxj9oq',
                     'scriptFile' => __DIR__ .'/index.php',
                     'scriptUrl' => '/index.php',
+                ],
+                'response' => [
+                    'format' => Response::FORMAT_JSON,
+                    'formatters' => [
+                        Response::FORMAT_JSON => 'tuyakhov\jsonapi\JsonApiResponseFormatter'
+                    ]
                 ]
             ],
             'vendorPath' => $this->getVendorPath(),
diff --git a/tests/actions/CreateActionTest.php b/tests/actions/CreateActionTest.php
index 9609db0..7295a92 100644
--- a/tests/actions/CreateActionTest.php
+++ b/tests/actions/CreateActionTest.php
@@ -44,7 +44,7 @@ public function testSuccess()
 
         $this->assertInstanceOf(ResourceModel::className(), $model = $action->run());
         $this->assertFalse($model->hasErrors());
-        $relationships = $model->getResourceRelationships();
+        $relationships = $model->getResourceRelationships(['extra_field1']);
         $this->assertArrayHasKey('extra_field1', $relationships);
         $this->assertInstanceOf(ResourceModel::className(), $relationships['extra_field1']);
         $this->assertEquals(124, $relationships['extra_field1']->id);
diff --git a/tests/actions/DeleteActionTest.php b/tests/actions/DeleteActionTest.php
new file mode 100644
index 0000000..01b2aff
--- /dev/null
+++ b/tests/actions/DeleteActionTest.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\tests\actions;
+
+use tuyakhov\jsonapi\actions\DeleteAction;
+use tuyakhov\jsonapi\tests\data\ActiveQuery;
+use tuyakhov\jsonapi\tests\data\ResourceModel;
+use tuyakhov\jsonapi\tests\TestCase;
+use yii\web\Controller;
+
+class DeleteActionTest extends TestCase
+{
+    public function testSuccess()
+    {
+        \Yii::$app->controller = new Controller('test', \Yii::$app);
+        $action = new DeleteAction('test', \Yii::$app->controller, [
+            'modelClass' => ResourceModel::className(),
+        ]);
+
+        ResourceModel::$id = 124;
+        ActiveQuery::$models = new ResourceModel();
+
+        $action->run(124);
+        $this->assertTrue(\Yii::$app->getResponse()->getIsEmpty());
+    }
+}
\ No newline at end of file
diff --git a/tests/actions/DeleteRelationshipActionTest.php b/tests/actions/DeleteRelationshipActionTest.php
new file mode 100644
index 0000000..5f58746
--- /dev/null
+++ b/tests/actions/DeleteRelationshipActionTest.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\tests\actions;
+
+use tuyakhov\jsonapi\actions\DeleteRelationshipAction;
+use tuyakhov\jsonapi\tests\data\ActiveQuery;
+use tuyakhov\jsonapi\tests\data\ResourceModel;
+use tuyakhov\jsonapi\tests\TestCase;
+use yii\data\ActiveDataProvider;
+use yii\web\Controller;
+use yii\web\ForbiddenHttpException;
+
+class DeleteRelationshipActionTest extends TestCase
+{
+    public function testSuccess()
+    {
+        $model = new ResourceModel();
+        $action = new DeleteRelationshipAction('test', new Controller('test', \Yii::$app), [
+            'modelClass' => ResourceModel::className()
+        ]);
+        ResourceModel::$related = [
+            'extraField1' => new ActiveQuery(ResourceModel::className(), ['multiple' => true]),
+            'extraField2' => new ActiveQuery(ResourceModel::className())
+        ];
+        $action->findModel = function ($id, $action) use($model) {
+            return $model;
+        };
+        $model->extraField1 = [new ResourceModel()];
+        \Yii::$app->request->setBodyParams(['ResourceModel' => ['type' => 'resource-models', 'id' => 123]]);
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run(1, 'extraField1'));
+        $this->expectException(ForbiddenHttpException::class);
+        $this->assertInstanceOf(ResourceModel::className(), $action->run(1, 'extraField2'));
+    }
+}
\ No newline at end of file
diff --git a/tests/actions/IndexActionTest.php b/tests/actions/IndexActionTest.php
new file mode 100644
index 0000000..75bc865
--- /dev/null
+++ b/tests/actions/IndexActionTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
+ */
+
+namespace tuyakhov\jsonapi\tests\actions;
+
+
+use tuyakhov\jsonapi\actions\IndexAction;
+use tuyakhov\jsonapi\tests\data\ActiveQuery;
+use tuyakhov\jsonapi\tests\data\ResourceModel;
+use tuyakhov\jsonapi\tests\TestCase;
+use yii\base\Controller;
+use yii\data\ActiveDataFilter;
+use yii\data\ActiveDataProvider;
+use yii\db\Query;
+
+class IndexActionTest extends TestCase
+{
+    public function testSuccess()
+    {
+        $action = new IndexAction('test', new Controller('test', \Yii::$app), [
+            'modelClass' => ResourceModel::className(),
+            'dataFilter' => [
+                'class' => ActiveDataFilter::className(),
+                'searchModel' => ResourceModel::className()
+            ]
+        ]);
+        $filter = [
+            'filter' => ['field1' => 'test,qwe'],
+            'sort' => 'field1,-field2'
+        ];
+        \Yii::$app->getRequest()->setQueryParams($filter);
+
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run());
+        $this->assertInstanceOf(Query::className(), $dataProvider->query);
+        $this->assertSame([
+            'IN',
+            'field1',
+            ['test', 'qwe']
+        ], $dataProvider->query->where);
+        $this->assertSame(['field1' => SORT_ASC, 'field2' => SORT_DESC], $dataProvider->getSort()->orders);
+    }
+
+    public function testValidation()
+    {
+        $action = new IndexAction('test', new Controller('test', \Yii::$app), [
+            'modelClass' => ResourceModel::className(),
+            'dataFilter' => [
+                'class' => ActiveDataFilter::className(),
+                'searchModel' => ResourceModel::className()
+            ]
+        ]);
+        \Yii::$app->getRequest()->setQueryParams(['filter' => ['field1' => 1]]);
+
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run());
+        $this->assertInstanceOf(Query::className(), $dataProvider->query);
+        $this->assertNull($dataProvider->query->where);
+    }
+
+    public function testPagination()
+    {
+        $action = new IndexAction('test', new Controller('test', \Yii::$app), [
+            'modelClass' => ResourceModel::className(),
+        ]);
+        ActiveQuery::$models = [new ResourceModel(), new ResourceModel()];
+        $params = ['page' => 1];
+        \Yii::$app->getRequest()->setQueryParams($params);
+
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run());
+        $this->assertSame(0, $dataProvider->getPagination()->page);
+
+        $params = ['page' => ['number' => 2, 'size' => 1]];
+        \Yii::$app->getRequest()->setQueryParams($params);
+
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run());
+
+        $this->assertSame(2, $dataProvider->getCount());
+        $this->assertSame(2, $dataProvider->pagination->getPageCount());
+        $this->assertSame(1, $dataProvider->pagination->getPageSize());
+        $this->assertSame(1, $dataProvider->pagination->getOffset());
+
+        // test invalid value
+        $params = ['page' => 1];
+        \Yii::$app->getRequest()->setQueryParams($params);
+
+        $this->assertInstanceOf(ActiveDataProvider::className(), $dataProvider = $action->run());
+
+        $this->assertSame(2, $dataProvider->getCount());
+        $this->assertSame(1, $dataProvider->pagination->getPageCount());
+        $this->assertSame($dataProvider->pagination->defaultPageSize, $dataProvider->pagination->getPageSize());
+        $this->assertSame(0, $dataProvider->pagination->getOffset());
+    }
+}
\ No newline at end of file
diff --git a/tests/actions/UpdateActionTest.php b/tests/actions/UpdateActionTest.php
index 2f1b6f5..988dcb3 100644
--- a/tests/actions/UpdateActionTest.php
+++ b/tests/actions/UpdateActionTest.php
@@ -1,9 +1,6 @@
 <?php
 /**
- * Created by PhpStorm.
- * User: anton
- * Date: 08/03/2017
- * Time: 19:07
+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
  */
 
 namespace tuyakhov\jsonapi\tests\actions;
@@ -49,7 +46,7 @@ public function testSuccess()
         $this->assertInstanceOf(ResourceModel::className(), $model = $action->run(1));
         $this->assertFalse($model->hasErrors());
         $this->assertEquals('test', $model->field1);
-        $relationships = $model->getResourceRelationships();
+        $relationships = $model->getResourceRelationships(['extra_field1']);
         $this->assertArrayHasKey('extra_field1', $relationships);
         $this->assertInstanceOf(ResourceModel::className(), $relationships['extra_field1']);
         $this->assertEquals(124, $relationships['extra_field1']->id);
diff --git a/tests/data/ResourceModel.php b/tests/data/ResourceModel.php
index b91b6c0..70d8c85 100644
--- a/tests/data/ResourceModel.php
+++ b/tests/data/ResourceModel.php
@@ -26,10 +26,26 @@ class ResourceModel extends Model implements ResourceInterface, LinksInterface
     public $username = '';
     public $extraField1 = 'testExtra';
     public $extraField2 = 42;
+    private $_id;
+
+    public function rules()
+    {
+        return [
+            ['field1', 'string']
+        ];
+    }
 
     public function getId()
     {
-        return static::$id;
+        if ($this->_id === null) {
+            $this->_id = static::$id;
+        }
+        return $this->_id;
+    }
+
+    public function setId($value)
+    {
+        $this->_id = $value;
     }
 
     public function fields()
@@ -72,9 +88,14 @@ public function getPrimaryKey($asArray = false)
         return $asArray ? [$this->getId()] : $this->getId();
     }
 
-    public function unlinkAll()
+    public function unlinkAll($name, $delete = false)
     {
-        return;
+        $this->$name = null;
+    }
+
+    public function unlink($name, $model)
+    {
+        array_pop($this->$name);
     }
 
     public function save()
@@ -82,6 +103,11 @@ public function save()
         return true;
     }
 
+    public function delete()
+    {
+        return true;
+    }
+
     public function getLinks()
     {
         return [