ark4ne / laravel-json-api
为 Laravel 设计的轻量级 JSON:API 资源
Requires
- php: ^8.1
- illuminate/collections: ^9.0|^10.0|^11.0
- illuminate/http: ^9.0|^10.0|^11.0
- illuminate/support: ^9.0|^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0|^10.0
- phpstan/phpstan: ^1.9.18
- phpunit/phpunit: ^9.5|^10.0
- dev-master
- v1.4.x-dev
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.x-dev
- v1.3.8
- v1.3.7
- v1.3.6
- v1.3.5
- v1.3.4
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3.0
- 1.2.x-dev
- v1.2.1
- v1.2.0
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.2
- v1.0.1
- v1.0.0
- v0.0.1
- v0.0.0
- v0.0.0-RC1
- dev-22-toresponse-set-a-wrong-name-header-content-type-instead-of-content-type
- dev-19-bug-exception-when-include-relationship-one
This package is auto-updated.
Last update: 2024-09-07 14:13:20 UTC
README
为 Laravel 提供的轻量级 {JSON:API} 资源。
安装
composer require ark4ne/laravel-json-api
配置
使用
此包是 Laravel 的 JsonResource
类的专门化。所有底层的 API 仍然存在,因此您可以在控制器中像使用基类 JsonResource
一样与 JsonApiResource
类进行交互
请求
此包允许通过 "include" 参数读取和动态包含在请求中请求的资源。
@see {json:api} fetching-includes
资源属性也将根据 "fields" 参数进行过滤。
@see {json:api} fetching-fields
您还可以通过规则 Rules\Includes
和 Rules\Fields
简单地验证给定资源的请求。
包含验证
use \Ark4ne\JsonApi\Requests\Rules\Includes; use \Illuminate\Foundation\Http\FormRequest; class UserFetchRequest extends FormRequest { public function rules() { return [ 'include' => [new Includes(UserResource::class)], ] } }
Rules\Includes
将验证 include
是否与用户资源模式(由关系确定)完全匹配。
字段验证
use \Ark4ne\JsonApi\Requests\Rules\Fields; use \Illuminate\Foundation\Http\FormRequest; class UserFetchRequest extends FormRequest { public function rules() { return [ 'fields' => [new Fields(UserResource::class)], ] } }
Rules\Fields
将验证 fields
是否与用户资源模式(由属性和关系确定)完全匹配。
自定义验证消息
资源
可实现的方法
protected function toType(Request $request): string; protected function toIdentifier(Request $request): int|string; protected function toAttributes(Request $request): iterable; protected function toRelationships(Request $request): iterable; protected function toResourceMeta(Request $request): ?iterable; protected function toMeta(Request $request): ?iterable;
示例
use Ark4ne\JsonApi\Resources\JsonApiResource; use Illuminate\Http\Request; class UserResource extends JsonApiResource { protected function toAttributes(Request $request): iterable { return [ 'name' => $this->name, 'email' => $this->email, ]; } protected function toResourceMeta(Request $request): ?iterable { return [ 'created_at' => $this->created_at->format(DateTimeInterface::ATOM), 'updated_at' => $this->updated_at->format(DateTimeInterface::ATOM), ]; } protected function toRelationships(Request $request): iterable { return [ 'posts' => PostResource::relationship(fn() => $this->posts, fn() => [ 'self' => "https://api.example.com/user/{$this->id}/relationships/posts", 'related' => "https://api.example.com/user/{$this->id}/posts", ]), 'comments' => CommentResource::relationship(fn() => $this->whenLoaded('comments')), ]; } }
toType
返回资源类型。
protected function toType(Request $request): string { return 'user'; }
默认返回模型类在短横线格式中: App\Models\MyPost
=> my-post
toIdentifier
@see {json:api} resource-identifier
返回资源标识符。
protected function toIdentifier(Request $request): int|string { return $this->id; }
默认返回模型 id。
toAttributes
@see {json:api} resource-attributes
返回资源属性。
protected function toAttributes(Request $request): iterable { return [ 'name' => $this->name, 'email' => $this->email, ]; }
Laravel 条件属性
@see laravel: eloquent-conditional-attributes
支持 Laravel 条件属性。
protected function toAttributes(Request $request): array { return [ 'name' => $this->name, 'email' => $this->email, // with lazy evaluation 'hash64' => fn() => base64_encode("{$this->id}-{$this->email}"), // Conditional attribute 'secret' => $this->when($request->user()->isAdmin(), 'secret-value'), // Merging Conditional Attributes // use applyWhen insteadof mergeWhen for keep fields // useful for fields request rules validation $this->applyWhen($request->user()->isAdmin(), [ 'first-secret' => 123, 'second-secret' => 456.789, ]), ]; }
描述属性
@see 描述符号
protected function toAttributes(Request $request): array { return [ 'name' => $this->string(), // pass key to describer $this->string('email'), // with lazy evaluation 'hash64' => $this->string(fn() => base64_encode("{$this->id}-{$this->email}")), // Conditional attribute $this->string('secret')->when($request->user()->isAdmin(), 'secret-value'), // Merging Conditional Attributes $this->applyWhen($request->user()->isAdmin(), [ 'first-secret' => $this->integer(fn() => 123), 'second-secret' => $this->float(fn() => 456.789), ]), ]; }
toRelationships
@see {json:api} resources-relationships
返回资源关系。
所有关系 必须 使用 ModelResource::relationship
创建。这允许生成表示资源的模式,从而验证请求包含内容。
如果您的关联应该是通过 ::collection(...)
方法创建的集合,则可以使用 ->asCollection()
。
如果您希望仅在请求包含中存在时加载关联数据,则可以使用 ->whenIncluded()
方法。
protected function toRelationships(Request $request): array { return [ 'avatar' => AvatarResource::relationship($this->avatar), // with conditional relationship 'administrator' => $this->when($request->user()->isAdmin(), UserResource::relationship(fn() => $this->administrator), // as collection, with conditional value 'comments' => CommentResource::relationship(fn() => $this->whenLoaded('comments'))->asCollection(), // with relationship (allow to include links and meta on relation) 'posts' => PostResource::relationship(fn() => $this->posts)->withLinks(fn() => [ 'self' => "https://api.example.com/user/{$this->id}/relationships/posts", 'related' => "https://api.example.com/user/{$this->id}/posts", ])->asCollection(), ]; }
toRelationships
必须返回一个数组,键为字符串,值为 JsonApiResource
或 JsonApiCollection
。
Laravel 条件关系
@see laravel: eloquent-conditional-relationships
支持Laravel条件关系。
protected function toRelationships(Request $request): array { return [ 'avatar' => AvatarResource::relationship($this->avatar), // as collection, with condition 'comments' => CommentResource::relationship(fn() => $this->whenLoaded('comments'))->asCollection(), // with relationship (allow to include links and meta on relation) 'posts' => PostResource::relationship(fn() => $this->posts) ->asCollection(), ]; }
描述属性
@see 描述符号
protected function toRelationships(Request $request): array { return [ 'avatar' => $this->one(AvatarResource::class), // custom relation name 'my-avatar' => $this->one(AvatarResource::class, 'avatar'), // as collection, with condition 'comments' => $this->many(CommentResource::class) ->whenLoaded(), // with relationship (allow to include links and meta on relation) 'posts' => $this->many(PostResource::class) ->links(fn() => [ 'self' => "https://api.example.com/posts/{$this->resource->id}/relationships/posts", 'related' => "https://api.example.com/posts/{$this->resource->id}/posts", ]) ->meta(fn() => [ 'total' => $this->integer(fn() => $this->resource->posts()->count()), ]), ]; }
关系链接和元数据
@see {json:api}: relation-linkage
@see {json:api}: relation-meta
返回关系链接和元数据。
protected function toRelationships(Request $request): array { return [ 'posts' => PostResource::relationship(fn() => $this->posts)->withLinks(fn() => [ // links 'self' => "https://api.example.com/user/{$this->id}/relationships/posts", 'related' => "https://api.example.com/user/{$this->id}/posts", ])->withMeta(fn() => [ // meta 'creator' => $this->name, ]) ->asCollection(), ]; }
toLinks
@see {json:api}: resource-linkage
返回资源链接。
protected function toLinks(Request $request): ?array { return [ 'self' => route('api.user.show', ['id' => $this->id]), ]; }
toResourceMeta
@see {json:api}: resource-meta
@see {json:api}: document-meta
返回资源元数据。
protected function toResourceMeta(Request $request): ?iterable { return [ 'created_at' => $this->created_at->format(DateTimeInterface::ATOM), 'updated_at' => $this->updated_at->format(DateTimeInterface::ATOM), ]; }
toMeta
@see {json:api}: document-meta
返回文档元数据。
protected function toMeta(Request $request): ?iterable { return [ "copyright": "Copyright 2022 My Awesome Api", ]; }
集合
@see laravel: resource-collection
集合在JsonApiCollection
中实现。
使用方式与Laravel集合相同。
UserResource::collection(User::all()); // => JsonApiCollection
描述性符号
值方法
关系方法
枚举
方法enum
允许获取支持枚举的枚举值或单元枚举的名称。
根据结构
/// Role.php enum Role { case ADMIN; case USER; } /// State.php enum State:int { case ACTIVE = 1; case INACTIVE = 0; } /// User.php class User extends Model { $casts = [ 'role' => Role::class, 'state' => State::class, ]; }
以下资源属性
// UserResource.php protected function toAttributes(Request $request): array { return [ 'status' => $this->enum(), 'role' => $this->enum(), ]; }
将返回
[ "status": 1, "role": "ADMIN" ]