bavix / json-api
PHP 中的 JSON-API 响应
Requires
- php: ^7.0|^8.0
Requires (Dev)
- phpunit/phpunit: ^4.8 || ^5.0
README
JSON-API 在 PHP 中的响应。
与规范版本 1.0 兼容。
安装
通过 Composer
composer require bavix/json-api
用法
use Tobscure\JsonApi\Document; use Tobscure\JsonApi\Collection; // Create a new collection of posts, and specify relationships to be included. $collection = (new Collection($posts, new PostSerializer)) ->with(['author', 'comments']); // Create a new JSON-API document with that collection as the data. $document = new Document($collection); // Add metadata and links. $document->addMeta('total', count($posts)); $document->addLink('self', 'http://example.com/api/posts'); // Output the document as JSON. echo json_encode($document);
元素
JSON-API 规范将 资源对象 描述为包含单个资源信息的对象,将 集合对象 描述为包含多个资源信息的对象。在此包中
Tobscure\JsonApi\Resource
表示一个 资源对象Tobscure\JsonApi\Collection
表示一个 集合对象
资源和集合都被称为 元素。在概念上与 JSON-API 规范描述的相同,资源可以与任何数量的其他元素(资源用于一对一关系,集合用于一对多)有 关系。同样,集合可以包含多个资源。
JSON-API 文档可以包含一个主元素。主元素将被递归解析以与其他元素的关系;这些元素将被添加到文档中作为 包含 的资源。
稀疏字段集
您可以使用 fields
方法指定要包含在元素上的哪些字段(属性和关系)。您必须提供一个按资源类型组织的多维数组
$collection->fields(['posts' => ['title', 'date']]);
序列化器
序列化器负责为某种资源类型构建属性和关系。序列化器必须实现 Tobscure\JsonApi\SerializerInterface
。提供了一个具有一些基本功能的 AbstractSerializer
。至少,序列化器必须指定其 类型 并提供一个方法来转换 属性
use Tobscure\JsonApi\AbstractSerializer; class PostSerializer extends AbstractSerializer { protected $type = 'posts'; public function getAttributes($post, array $fields = null) { return [ 'title' => $post->title, 'body' => $post->body, 'date' => $post->date ]; } }
默认情况下,资源对象的 id 属性将被设置为模型上的 id
属性。序列化器可以提供一个方法来覆盖此设置
public function getId($post) { return $post->someOtherKey; }
关系
AbstractSerializer
允许您为资源中存在的每个关系定义一个公共方法。关系方法应返回一个 Tobscure\JsonApi\Relationship
实例。
public function comments($post) { $element = new Collection($post->comments, new CommentSerializer); return new Relationship($element); }
默认情况下,AbstractSerializer
将将关系名称从 kebab-case
和 snake_case
转换为 camelCase
方法名称,并在序列化器上调用该名称。如果您希望自定义此行为,您可能需要覆盖 getRelationship
方法
public function getRelationship($model, $name) { // resolve Relationship called $name for $model }
元数据 & 链接
Document
、Resource
和 Relationship
类允许您添加元信息
$document = new Document; $document->addMeta('key', 'value'); $document->setMeta(['key' => 'value']);
它们还允许以类似的方式添加链接
$resource = new Resource($data, $serializer); $resource->addLink('self', 'url'); $resource->setLinks(['key' => 'value']);
您还可以轻松地添加分页链接
$document->addPaginationLinks( 'url', // The base URL for the links [], // The query params provided in the request 40, // The current offset 20, // The current limit 100 // The total number of results );
序列化器也可以提供链接和/或元数据
use Tobscure\JsonApi\AbstractSerializer; class PostSerializer extends AbstractSerializer { // ... public function getLinks($post) { return ['self' => '/posts/' . $post->id]; } public function getMeta($post) { return ['some' => 'metadata for ' . $post->id]; } }
注意:资源的链接和元数据将覆盖具有相同键的序列化器的那些!
参数
Tobscure\JsonApi\Parameters
类允许您轻松地根据规范解析和验证查询参数。
use Tobscure\JsonApi\Parameters; $parameters = new Parameters($_GET);
getInclude
获取请求包含的关联关系。提供一个可用的关系路径数组;如果存在其他任何内容,将抛出 InvalidParameterException
异常。
// GET /api?include=author,comments $include = $parameters->getInclude(['author', 'comments', 'comments.author']); // ['author', 'comments']
getFields
获取请求包含的字段,键为资源类型。
// GET /api?fields[articles]=title,body $fields = $parameters->getFields(); // ['articles' => ['title', 'body']]
getSort
获取请求的排序标准。提供一个可以排序的可用字段数组;如果存在其他任何内容,将抛出 InvalidParameterException
异常。
// GET /api?sort=-created,title $sort = $parameters->getSort(['title', 'created']); // ['created' => 'desc', 'title' => 'asc']
getLimit 和 getOffset
使用基于页面或偏移的策略获取偏移量数字和要显示的资源数量。 getLimit
接受一个可选的最大值。如果计算出的偏移量小于零,将抛出 InvalidParameterException
异常。
// GET /api?page[number]=5&page[size]=20 $limit = $parameters->getLimit(100); // 20 $offset = $parameters->getOffset($limit); // 80 // GET /api?page[offset]=20&page[limit]=200 $limit = $parameters->getLimit(100); // 100 $offset = $parameters->getOffset(); // 20
错误处理
您可以使用 Tobscure\JsonApi\ErrorHandler
类将捕获的异常转换为 JSON-API 错误文档。您必须注册适当的 Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface
实例。
try { // API handling code } catch (Exception $e) { $errors = new ErrorHandler; $errors->registerHandler(new InvalidParameterExceptionHandler); $errors->registerHandler(new FallbackExceptionHandler); $response = $errors->handle($e); $document = new Document; $document->setErrors($response->getErrors()); return new JsonResponse($document, $response->getStatus()); }
贡献
如果您遇到问题或有很多好主意,请随意发送拉取请求或创建问题。任何输入都受欢迎!
运行测试
$ phpunit
许可
此代码根据 MIT 许可证 发布。这意味着只要保留版权声明和随附的许可文件,您几乎可以做任何事情。