sycho / json-api
PHP中的JSON-API响应
Requires
- php: ^7.3 || ^8.0
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^9.0
README
在PHP中实现JSON-API响应。
兼容规范版本1.0。
安装
通过Composer
composer require tobscure/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
获取使用基于页面或偏移量的策略显示的资源偏移数和数量。如果计算的偏移量小于零,将抛出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 许可证 发布。这意味着您可以几乎用它做任何事情,只要保留版权声明和随附的许可证文件即可。