tuyakhov / yii2-json-api
Yii 框架 JSON API 规范的实现
Requires
- yiisoft/yii2: ^2.0.13
Requires (Dev)
- phpunit/phpunit: 5.5.*
- dev-master
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v0.1.8
- v0.1.7
- v0.1.6
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- v0.0.11
- v0.0.10
- v0.0.9
- v0.0.8
- v0.0.7
- v0.0.6
- v0.0.5
- v0.0.4
- v0.0.3
- v0.0.2
- v0.0.1
- dev-allow_deleting_resources
- dev-improve_pagination
- dev-fix_empty_resources
- dev-filtering
- dev-improve_documentation
- dev-add_delete_action
- dev-fix_empty_body
- dev-clear_relationships
- dev-error_formatting
- dev-inclusion
- dev-remove_duplicates
- dev-filters
- dev-rest_actions
This package is auto-updated.
Last update: 2024-09-23 21:34:23 UTC
README
Yii 框架 JSON API 规范的实现
安装
通过 composer 安装此扩展是首选方式。
运行
php composer.phar require --prefer-dist tuyakhov/yii2-json-api "*"
或者在您的 composer.json
文件的 require 部分添加
"tuyakhov/yii2-json-api": "*"
to the require section of your composer.json
file.
数据序列化和内容协商
控制器
class Controller extends \yii\rest\Controller { public $serializer = 'tuyakhov\jsonapi\Serializer'; public function behaviors() { return ArrayHelper::merge(parent::behaviors(), [ 'contentNegotiator' => [ 'class' => ContentNegotiator::className(), 'formats' => [ 'application/vnd.api+json' => Response::FORMAT_JSON, ], ] ]); } }
默认情况下,type
的值会自动转换为复数。您可以通过设置 tuyakhov\jsonapi\Serializer::$pluralize
属性来改变此行为
class Controller extends \yii\rest\Controller { public $serializer = [ 'class' => 'tuyakhov\jsonapi\Serializer', 'pluralize' => false, // makes {"type": "user"}, instead of {"type": "users"} ]; }
定义模型
- 让我们定义
User
模型和声明一个articles
关联
use tuyakhov\jsonapi\ResourceTrait; use tuyakhov\jsonapi\ResourceInterface; class User extends ActiveRecord implements ResourceInterface { use ResourceTrait; public function getArticles() { return $this->hasMany(Article::className(), ['author_id' => 'id']); } }
- 现在我们需要定义
Article
模型
use tuyakhov\jsonapi\ResourceTrait; use tuyakhov\jsonapi\ResourceInterface; class Article extends ActiveRecord implements ResourceInterface { use ResourceTrait; }
- 结果
User
模型将被序列化为正确的 JSON API 资源对象
{ "data": { "type": "users", "id": "1", "attributes": { // ... this user's attributes }, "relationships": { "articles": { // ... this user's articles } } } }
控制 JSON API 输出
JSON 响应由 tuyakhov\jsonapi\JsonApiResponseFormatter
类生成,该类将内部使用 yii\helpers\Json
辅助器。此格式化器可以通过不同的选项进行配置,例如 $prettyPrint
选项,这对于开发中更好的可读性响应非常有用,或者 $encodeOptions
以控制 JSON 编码的输出。
格式化器可以在应用程序配置中的 response
应用组件的 yii\web\Response::formatters
属性中进行配置,如下所示
'response' => [ // ... 'formatters' => [ \yii\web\Response::FORMAT_JSON => [ 'class' => 'tuyakhov\jsonapi\JsonApiResponseFormatter', 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, ], ], ],
链接
您的资源类可能通过实现 LinksInterface
来支持 HATEOAS。该接口包含一个 getLinks()
方法,该方法应返回一个链接列表。通常,您应该返回至少一个代表资源对象自身 URL 的 self
链接。为了使链接出现在关系中,getLinks()
方法应返回 self
链接。基于此链接,每个关系将生成 self
和 related
链接。默认情况下,这是通过在主模型的 self
链接末尾附加关系名称来完成的,您可以简单地通过覆盖 getRelationshipLinks()
方法来改变这种行为。例如,
class User extends ActiveRecord implements ResourceInterface, LinksInterface { use ResourceTrait; public function getLinks() { return [ Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true), ]; } }
结果
{ "data": { "type": "users", "id": "1", // ... this user's attributes "relationships": { "articles": { // ... article's data "links": { "self": {"href": "http://yourdomain.com/users/1/relationships/articles"}, "related": {"href": "http://yourdomain.com/users/1/articles"} } } } "links": { "self": {"href": "http://yourdomain.com/users/1"} } } }
分页
查询参数家族 page
保留用于分页。此库实现了一种基于页面的策略,并允许使用查询参数,例如 page[number]
和 page[size]
示例: http://yourdomain.com/users?page[number]=3&page[size]=10
启用 JSON API 输入
要使 API 能够接受 JSON API 格式的输入数据,请配置请求应用程序组件的 [[yii\web\Request::$parsers|parsers]] 属性,以使用 [[tuyakhov\jsonapi\JsonApiParser]] 进行 JSON 输入
'request' => [ 'parsers' => [ 'application/vnd.api+json' => 'tuyakhov\jsonapi\JsonApiParser', ] ]
默认情况下,它解析 HTTP 请求正文,以便您可以使用用户输入填充模型属性。例如,请求正文
{ "data": { "type": "users", "id": "1", "attributes": { "first-name": "Bob", "last-name": "Homster" } } }
将被解析为以下数组
// var_dump($_POST); [ "User" => [ "first_name" => "Bob", "last_name" => "Homster" ] ]
因此,您可以通过调用 \Yii::$app->request->post()
来访问请求正文,并简单地使用输入数据填充模型
$model = new User(); $model->load(\Yii::$app->request->post());
默认情况下,类型 users
将转换为 User
(单数,驼峰式)与模型的 formName()
方法相对应(您可以覆盖它)。您可以覆盖 JsonApiParser::formNameCallback
属性,该属性引用一个将 'type' 成员转换为表单名称的回调。您还可以通过设置 JsonApiParser::memberNameCallback
属性来改变成员名称到变量名称的默认转换行为('first-name' 转换为 'first_name')。
示例
控制器
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', ], ]; } }
模型
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) ]; } }
配置文件 config/main.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'], ], ] ] // ... ] // ... ]