dkx/json-api
该软件包已被废弃且不再维护。未建议替代软件包。
Json api 转换器
2.0.2
2020-02-05 14:31 UTC
Requires
- php: ^7.3
- dkx/json-api-serializer: ^2.0.0
Requires (Dev)
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^0.11.8
- phpstan/phpstan-phpunit: ^0.11.2
- phpstan/phpstan-strict-rules: ^0.11.1
- phpunit/phpunit: ^8.0
README
框架无关的PHP JsonApi转换器。
安装
$ composer require dkx/json-api
转换器
<?php
use DKX\JsonApi\Item;
use DKX\JsonApi\Transformer;
use DKX\JsonApi\TransformContext;
class BookTransformer implements Transformer
{
public function supports(object $item): bool
{
return $item instanceof Book;
}
public function transform(object $item, TransformContext $ctx): Item
{
if (!$item instanceof Book) {
throw new ShouldNotHappenException;
}
return new Item('book', $item->id, [
Item::ATTRIBUTES => [
'title' => $item->title,
'content' => $item->content,
],
]);
}
}
使用
<?php
use DKX\JsonApi\Manager;
$manager = new Manager;
$manager->addTransformer(new BookTransformer);
$json = $manager->itemToArray($books->getById(5));
// or collection
$json = $manager->collectionToArray($books->getAll());
关系
<?php
use DKX\JsonApi\Item;
new Item('book', $item->id, [
Item::ATTRIBUTES => [
'title' => $item->title,
'content' => $item->content,
],
Item::RELATIONSHIPS => [
'user' => $item->user,
],
]);
现在我们可以这样加载user
关系
<?php
$manager->itemToArray($books->getOneById(5), ['user']);
懒加载关系
<?php
use DKX\JsonApi\Item;
new Item('book', $item->id, [
Item::ATTRIBUTES => [
'title' => $item->title,
'content' => $item->content,
],
Item::RELATIONSHIPS => [
'user' => function () use ($item) {
return $users->getOneById($item->userId);
},
],
]);
解决N+1问题
<?php
use DKX\JsonApi\Deferred;
use DKX\JsonApi\Item;
new Item('book', $item->id, [
Item::ATTRIBUTES => [
'title' => $item->title,
'content' => $item->content,
],
Item::RELATIONSHIPS => [
'user' => function () use ($item) {
MyUserBuffer::add($item->userId);
return new Deferred(function () use ($item) {
MyUserBuffer::loadBuffered();
return MyUserBuffer::get($item->userId);
});
},
],
]);
在这里解决N+1问题的逻辑是将所有ID存储到缓冲区中,然后通过一个查询(使用IN(?)
SQL子句)加载所有实体,然后从加载的数组中选取所需的实体。
批量处理
Batch
只是Deferred
的另一种形式,使用更简单。
<?php
use DKX\JsonApi\Batch;
use DKX\JsonApi\Item;
new Item('book', $item->id, [
Item::ATTRIBUTES => [
'title' => $item->title,
'content' => $item->content,
],
Item::RELATIONSHIPS => [
'user' => function () use ($item) {
return new Batch('bookUsersById', $item->userId, function (array $ids) {
return $usersRepository->getByIds($ids);
}, function (array $users) use ($item) {
return $users[$item->userId];
});
},
],
]);
每个Batch
必须有一个作用域(例如:bookUsersById
),用于收集所有关系ID(Batch
的第二个参数)。
第一个回调必须返回一个包含所有可能通过所有ID(在作用域中收集)选择的关系的数组。
第二个回调接收第一个回调返回的数据,必须为当前项返回一个关系数据。