soyhuce / laravel-json-resources
针对 Laravel 的具有观点的 JsonResource
Requires
- php: ^8.2
- illuminate/contracts: ^10.0 || ^11.0
- illuminate/http: ^10.0 || ^11.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.7
- larastan/larastan: ^2.0.1
- nunomaduro/collision: ^7.10 || ^8.0
- orchestra/testbench: ^8.0 || ^9.0
- pestphp/pest: ^2.24
- pestphp/pest-plugin-laravel: ^2.2
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
README
永远不要在生产环境中在 JsonResource 序列化时执行数据库查询,不要产生开销!
安装
您可以通过 composer 安装此包
composer require soyhuce/laravel-json-resources
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="json-resources-config"
用法
此包提供了一个基类 Soyhuce\JsonResources\JsonResource。
它提供了一个简化的数据序列化接口
class UserResource extends \Soyhuce\JsonResources\JsonResource { /** * @return array<string, mixed> */ public function format(): array { return [ 'id' => $this->id, 'email' => $this->email, ]; } }
仍然可以使用 public function toArray($request): array 方法。
还提供了一个基类 \Soyhuce\JsonResources\ResourceCollection。
禁止执行数据库查询
使用此基资源,您可以在序列化期间禁止执行数据库查询。
您只需在 json-resources.forbid-database-queries 配置中激活此选项。
此配置旨在用于本地环境,但在生产环境中应关闭。它允许您测试所有必需的关系是否正确加载(例如在功能测试中),同时在生产环境中限制开销。
例如
class UserResource extends \Soyhuce\JsonResources\JsonResource { /** * @return array<string, mixed> */ public function format(): array { return [ 'id' => $this->id, 'role' => $this->role->label, ]; } } class UserController { public function index(): \Illuminate\Http\Resources\Json\JsonResource { return UserResource::collection(User::all()); } }
每次执行请求都会引发一个 DatabaseQueryDetected 异常
2 queries detected in resource : select * from "roles" where "id" = 2 select * from "roles" where "id" = 1
匿名资源
在某些情况下,可能需要匿名资源。
例如,如果用户的角色是可空的,则可以
class UserResource extends \Soyhuce\JsonResources\JsonResource { /** * @return array<string, mixed> */ public function format(): array { return [ 'id' => $this->id, 'role' => $this->role !== null ? [ 'id' => $this->role->id, 'label' => $this->role->label, ] : null ]; } }
通过一个 AnonymousResource,您可以这样做
class UserResource extends \Soyhuce\JsonResources\JsonResource { /** * @return array<string, mixed> */ public function format(): array { return [ 'id' => $this->id, 'role' => new \Soyhuce\JsonResources\AnonymousResource( $this->role, fn (Role $role) => [ 'id' => $this->role->id, 'label' => $this->role->label, ] ) ]; } }
如果用户有一个角色,您将得到
{
"data": {
"id": 1,
"role": {
"id": 2,
"label": "classic"
}
}
}
如果用户没有角色,您将得到
{
"data": {
"id": 1,
"role": null
}
}
从控制器返回匿名资源
从控制器返回匿名资源是可能的。如果提供的数据为 null,您不会得到 'null',而是一个空数组 []。
class SomeController { public function show() { return \Soyhuce\JsonResources\AnonymousResource::make( $this->searchSomeItem(), // returns Item|null fn (Item $item) => [ 'label' => $item->label, 'prop' => $item->prop ] ); } }
如果找到了项目
{
"data": {
"label": "the label",
"prop": 14
}
}
如果项目是 null
{
"data": []
}
注意:不支持匿名资源集合
无格式的匿名资源
您可以选择不带回调返回匿名资源。在这种情况下,资源将原样返回。
class SomeController { public function show() { $foo = $this->fetchFoo(); $bars = $this->fetchBars(); return \Soyhuce\JsonResources\AnonymousResource::make([ 'foo' => FooResource::make($foo), 'bars' => BarResource::collection($bars), ]); } }
返回的 json 将具有以下形式
{
"data": {
"foo": {
// some foo data
},
"bar": [
{
// some bar data
},
{
// some bar data
}
]
}
}
Json 编码
默认情况下,所有返回的 json 都使用 JSON_PRESERVE_ZERO_FRACTION 选项进行编码。
功能测试
当应用处于 local 或 testing 环境时,JsonResource 和 ResourceCollection 类会在响应中添加一个 X-Json-Resource 标头。
此标头将包含用于生成响应的实际资源类,可用于功能测试以验证使用了哪个资源。
为了测试这一点,您可以使用 TestResponse::assertJsonResource(TheResource::class) 方法。
use Soyhuce\JsonResources\Tests\Fixtures\User; class SomeController { public function index(): JsonResouce { return UserResource::collection(User::all()); } public function show(User $user): JsonResource { return UserResource::make($user); } } class UserTest extends TestCase { /** @test */ public function indexUsesUserResource(): void { $this->getJson('users') ->assertOk() ->assertJsonResource(UserResource::class); } /** @test */ public function showUsesUserResource(): void { $user = User:::factory()->createOne(); $this->getJson("users/{$user->id}") ->assertOk() ->assertJsonResource(UserResource::class); } }
单元测试
对 JsonResource 进行单元测试可能很有用。您可以使用 soyhuce/laravel-testing 进行此操作。
在这种情况下,您可能需要允许执行数据库查询。您可以通过调用
\Soyhuce\JsonResources\JsonResources::allowDatabaseQueries();
测试
composer test
变更日志
请参阅 CHANGELOG 了解最近更改的详细信息。
贡献
请参阅 CONTRIBUTING 了解详细信息。
安全漏洞
请查看我们如何报告安全漏洞的安全策略。
致谢
许可协议
MIT 许可协议(MIT)。有关更多信息,请参阅许可文件。