aaronbullard / dogpile
JSON:API 辅助库,用于干净地导入包含的关联关系
Requires
- php: >=7.0
- tightenco/collect: 5.5.*
Requires (Dev)
- mockery/mockery: ^1.1
- phpunit/phpunit: 6.5.*
This package is auto-updated.
Last update: 2024-09-27 09:19:14 UTC
README
JSON:API 辅助库,用于干净地导入包含的关联关系
安装
库
git clone git@github.com:aaronbullard/dogpile.git
Composer
composer require aaronbullard/dogpile
测试
composer test
用法
首先,访问https://jsonapi.fullstack.org.cn获取JSON:API标准的文档。此库试图简化和模块化API调用中包含的相关资源对象。
Ex. GET /posts/1?include=author,comments,comments.author
此库将快速查询并包含与资源相关联的'作者'和'评论'。要做到这一点,需要实现一些接口。
// Example contoller method for GET /posts/1?include=author,comments,comments.author public function show(Request $httpRequest): JsonResponse { $postId = $httpRequest->get('postId'); $includes = explode(',', $httpRequest->get('include')); //['author', 'comments', 'comments.author']; // In this example, $post implements the Dogpile\Contracts\Resource interface; $post = $this->myPostRepo->find($postId); // Example of using Dogpile\ResourceManager::class $includedResources = $this->resourceManager->newQuery() ->setRelationships($post->relationships()) ->include(...$includes) ->query(); return new JsonResponse([ 'data' => $post->toJsonapi(), // or however you want to transform your model 'included' => array_map(function($resource){ return $resource->toJsonapi(); }, $includedResources); ], 200); }
工作原理
Dogpile\ResourceManager类包含每个资源类型的多个ResourceQuery对象。当提供一个包含关联关系的数组时,Dogpile\QueryBuilder类将使用RelationshipCollection中的ResourceIdentifiers通过RepositoryQuery::findHavingIds()方法查询资源。每个资源只会查询一次。
设置
首先
Dogpile需要为每个资源实现Dogpile\Contracts\ResourceQuery接口。例如,你将想要为'people'(查询作者)实现一个,以及一个为'comments'。
<?php namespace Dogpile\Contracts; use Dogpile\Collections\ResourceCollection; interface ResourceQuery { /** * Returns the type of Resource Objects * * @return void */ public function resourceType(): string; /** * Queries the resource based on the ids provided * * Must return an array of objects implementing the ResourceObject interface * * @param array $ids * @return array * @throws NotFoundException */ public function findHavingIds(array $ids): ResourceCollection; }
第二
将你的ResourceQuery处理程序注册到Dogpile\ResourceManager中
<?php // some bootstrap file use Dogpile\ResourceManager; $conn = $app['database_connection']; $app[ResouceManager::class] = new ResourceManager( new AuthorsResourceQuery($conn), new CommentsResourceQuery($conn) );
第三
Dogpile\Contracts\ResourceQuery::findHavingIds()必须返回一个包含实现Dogpile\Contracts\Resource接口的对象的Dogpile\Collections\ResourceCollection类。
<?php namespace Dogpile\Contracts; use Dogpile\Collections\RelationshipCollection; interface Resource { /** * Resource type * * @return string */ public function type(): string; /** * Resource id * * @return string */ public function id(): string; /** * Returns an array of ResourceIdentifiers * * @return RelationshipCollection */ public function relationships(): RelationshipCollection; }
第四
如上所述,每个资源对象必须实现Resource::realtionships()接口,该接口返回一个RelationshipCollection类。Dogpile\Collections\RelationshipCollection类可以按以下方式实现。
<?php // Example data $jsonapiData = [ 'type' => 'posts', 'id' => '42', 'attributes' => [ 'title' => 'Bridge of Death', 'body' => 'What is the airspeed velocity of an unladed swallow?' ], 'relationships' => [ 'author' => [ 'data' => ['type' => 'people', 'id' => '24'] ], 'comments' => [ 'data' => [ ['type' => 'comments', 'id' => '1'], ['type' => 'comments', 'id' => '2'], ['type' => 'comments', 'id' => '3'] ] ] ] ] // Example model use Dogpile\ResourceIdentifier; use Dogpile\Contracts\Resource; use Dogpile\Collections\RelationshipCollection; class SomeObjectModel implements Resource { protected $jsonapiData = []; public function __construct(array $jsonapiData) { $this->jsonapiData = $jsonapiData; } public function type(): string { return $this->jsonapiData['type']; } public function id(): string { return $this->jsonapiData['id']; } public function relationships(): RelationshipCollection { $collection = new RelationshipCollection(); // add author $authorIdent = $this->jsonapiData['relationships']['author']['data']; $collection->addRelationships('author', ResourceIdentifier::create($authorIdent['type'], $authorIdent['id'])); // add comments $commentIdentifiers = array_map(function($comment){ return ResourceIdentifier::create($comment['type'], $comment['id']); }, $this->jsonapiData['relationships']['comments']['data']); $collection->addRelationships('comments', ...$commentIdentifiers); return $collection; } }
更多示例,请参阅测试:tests\Functional\ResourceManagerTest.php