JSON:API
Resource这是一个轻量级的 Laravel API 资源包,可帮助你遵循 JSON:API
标准,内置支持稀疏字段集、复合文档等功能。
注意 这些文档并非旨在介绍
JSON:API
规范及相关概念,如果你还不熟悉,应该前往阅读规范。以下文档仅涵盖如何通过该包来实现规范。
目录
8.1
, 8.2
, 8.3
9.0
, 10.0
, 11.0
你可以使用 composer 从 Packagist 安装。
composer require timacdonald/json-api
该包提供的 JsonApiResource
类是 Laravel Eloquent API 资源的特殊化。所有公开的 API 仍然可以访问;例如,在控制器中,你可以像使用 Laravel 的 JsonResource
类一样使用 JsonApiResource
。
<?php namespace App\Http\Controllers; use App\Http\Resources\UserResource; use App\Models\User; class UserController { public function index() { $users = User::with([/* ... */])->paginate(); return UserResource::collection($users); } public function show(User $user) { $user->load([/* ... */]); return UserResource::make($user); } }
随着我们深入示例,你会看到在内部与该类交互时引入了新的 API,例如,不再使用 toArray()
方法。
JSON:API
资源让我们为 User
模型创建一个 UserResource
。在用户资源中,我们将在响应中公开用户的 name
、website
和 twitter_handle
。
首先我们创建一个继承 TiMacDonald\JsonApi\JsonApiResource
的新 API 资源。
<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { // }
现在我们将创建一个 $attributes
属性,并列出我们想要公开的模型属性。
<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { public $attributes = [ 'name', 'website', 'twitter_handle', ]; }
当向返回 UserResource
的端点发出请求时,例如:
Route::get('users/{user}', fn (User $user) => UserResource::make($user));
将返回以下 JSON:API
格式的数据:
{ "data": { "type": "users", "id": "74812", "attributes": { "name": "Tim", "website": "https://timacdonald.me", "twitter_handle": "@timacdonald87" } } }
🎉 你刚刚创建了你的第一个 JSON:API
资源 🎉
恭喜...真是太刺激了!
现在我们将深入添加资源的关系,但如果你想探索更复杂的属性功能,可以跳到前面:
可用的关系可以在 $relationships
属性中指定,类似于 $attributes
属性,但你可以使用键/值对来提供给定关系应使用的资源类。
我们将在资源上提供两个关系:
$user->team
: 一个 "toOne" / HasOne
关系。$user->posts
: 一个 "toMany" / HasMany
关系。<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { public $attributes = [ 'name', 'website', 'twitter_handle', ]; public $relationships = [ 'team' => TeamResource::class, 'posts' => PostResource::class, ]; }
假设键/值对遵循 '{myKey}' => {MyKey}Resource::class
的约定,可以省略类以进一步简化。
<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { public $attributes = [ 'name', 'website', 'twitter_handle', ]; public $relationships = [ 'team', 'posts', ]; }
客户端现在可以通过 include
查询参数请求这些关系。
GET /users/74812?include=posts,team
注意 除非调用客户端通过
include
查询参数请求,否则不会在响应中暴露关系。这是有意的,是JSON:API
规范的一部分。
{ "data": { "id": "74812", "type": "users", "attributes": { "name": "Tim", "website": "https://timacdonald.me", "twitter_handle": "@timacdonald87" }, "relationships": { "posts": { "data": [ { "type": "posts", "id": "25240" }, { "type": "posts", "id": "39974" } ] }, "team": { "data": { "type": "teams", "id": "18986" } } } }, "included": [ { "id": "25240", "type": "posts", "attributes": { "title": "So what is `JSON:API` all about anyway?", "content": "...", "excerpt": "..." } }, { "id": "39974", "type": "posts", "attributes": { "title": "Building an API with Laravel, using the `JSON:API` specification.", "content": "...", "excerpt": "..." } }, { "id": "18986", "type": "teams", "attributes": { "name": "Laravel" } } ] }
要了解更复杂的关系特性,你可能想跳到前面:
该包不会预加载 Eloquent 关系。如果关系未预加载,该包将即时延迟加载关系。我强烈建议使用 Spatie 的查询构建器包,它将根据 JSON:API
查询参数标准预加载你的模型。
Spatie 提供了关于如何使用该包的全面文档,但我会简要举例说明如何在控制器中使用它。
<?php namespace App\Http\Controllers; use App\Http\Resources\UserResource; use App\Models\User; use Spatie\QueryBuilder\QueryBuilder; class UserController { public function index() { $users = QueryBuilder::for(User::class) ->allowedIncludes(['team', 'posts']) ->paginate(); return UserResource::collection($users); } public function show($id) { $user = QueryBuilder::for(User::class) ->allowedIncludes(['team', 'posts']) ->findOrFail($id); return UserResource::make($user); } }
我们现在已经介绍了在资源上公开属性和关系的基础知识。我们现在将介绍更高级的主题,以便让你获得更大的控制权。
toAttributes()
正如我们在添加属性部分看到的,$attributes
属性是公开资源属性的最快方法。在某些情况下,你可能需要对公开的属性进行更大的控制。如果是这种情况,你可以实现 toAttributes()
方法。这将让你可以访问当前请求并允许条件逻辑。
<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { /** * @param \Illuminate\Http\Request $request * @return array<string, mixed> */ public function toAttributes($request) { return [ 'name' => $this->name, 'website' => $this->website, 'twitter_handle' => $this->twitter_handle, 'email' => $this->when($this->email_is_public, $this->email, '<private>'), 'address' => [ 'city' => $this->address('city'), 'country' => $this->address('country'), ], ]; } }
{ "data": { "id": "74812", "type": "users", "attributes": { "name": "Tim", "website": "https://timacdonald.me", "twitter_handle": "@timacdonald87", "email": "<private>", "address": { "city": "Melbourne", "country": "Australia" } } } }
稀疏字段集是 JSON:API
规范的一个特性,允许客户端指定他们想要接收的任何给定资源类型的属性。这允许更确定性的响应,同时也提高了服务器端性能并减小了有效载荷大小。稀疏字段集可以开箱即用于你的资源。
我们将在这里简要介绍它们,但我们建议阅读规范以了解更多信息。
例如,假设我们正在构建博客的索引页面。该页面将显示每篇文章的 title
和 excerpt
,以及文章作者的 name
。如果客户端愿意,他们可以将响应限制为仅包含每种资源类型所需的属性,并排除其他属性,例如文章的 content
和作者的 twitter_handle
。
为了实现这一点,我们将发送以下请求。
GET /posts?include=author&fields[posts]=title,excerpt&fields[users]=name
注意
include
查询参数键是author
,而稀疏字段集参数键是users
。这是因为作者就是用户,例如 Eloquentauthor()
关系返回User
模型。
{ "data": [ { "id": "25240", "type": "posts", "attributes": { "title": "So what is `JSON:API` all about anyway?", "excerpt": "..." }, "relationships": { "author": { "data": { "type": "users", "id": "74812" } } } }, { "id": "39974", "type": "posts", "attributes": { "title": "Building an API with Laravel, using the `JSON:API` specification.", "excerpt": "..." }, "relationships": { "author": { "data": { "type": "users", "id": "74812" } } } } ], "included": [ { "type": "users", "id": "74812", "attributes": { "name": "Tim" } } ] }
当不使用稀疏字段集时,资源会返回最大的属性有效载荷,即返回资源上声明的所有属性。如果你愿意,你可以要求使用稀疏字段集才能检索任何属性。
你可以在应用程序服务提供者中调用 useMinimalAttributes()
方法。
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use TiMacDonald\JsonApi\JsonApiResource; class AppServiceProvider extends ServiceProvider { public function boot() { JsonApiResource::useMinimalAttributes(); 对于计算成本较高的属性,可以设置为仅在需要包含在响应中时才进行评估,即它们未通过稀疏字段集或最小属性被排除。如果你在资源中与数据库交互或发送HTTP请求,这可能会很有用。 举个例子,假设我们为每个用户提供一个base64编码的头像。我们的实现是从内部的头像微服务下载头像。 ```php <?php namespace App\Http\Resources; use Illuminate\Support\Facades\Http; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { /** * @param \Illuminate\Http\Request $request * @return array<string, mixed> */ public function toAttributes($request) { return [ // ... 'avatar' => Http::get("https://avatar.example.com/{$this->id}")->body(), ]; } }
上面的实现即使在客户端通过稀疏字段集或最小属性排除 avatar
属性时,也会向我们的微服务发送HTTP请求。为了在不返回此属性时提高性能,我们可以将值包装在一个 Closure
中。只有在需要返回 avatar
时,才会评估这个 Closure
。
<?php namespace App\Http\Resources; use Illuminate\Support\Facades\Http; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { /** * @param \Illuminate\Http\Request $request * @return array<string, mixed> */ public function toAttributes($request) { return [ // ... 'avatar' => fn () => Http::get("https://avatar.example.com/{$this->id}")->body(), ]; } }
toRelationships()
正如我们在添加关系部分看到的,$relationships
属性是为资源指定可用关系的最快方式。在某些情况下,你可能需要对提供的关系进行更多控制。如果是这种情况,你可以实现 toRelationships()
方法。这将允许你访问当前请求并进行条件逻辑。
值必须始终包装在一个 Closure
中,只有在客户端请求关系时才会调用。
<?php namespace App\Http\Resources; use TiMacDonald\JsonApi\JsonApiResource; class UserResource extends JsonApiResource { /** * @param \Illuminate\Http\Request $request * @return array<string, (callable(): \TiMacDonald\JsonApi\JsonApiResource|\TiMacDonald\JsonApi\JsonApiResourceCollection|\Illuminate\Http\Resources\PotentiallyMissing)> */ public function toRelationships($request) { return [ 'team' => fn () => TeamResource::make($this->team), 'posts' => fn () => $request->user()->is($this->resource) ? PostResource::collection($this->posts) : PostResource::collection($this->posts->where('published', true)), ]; } }
undefined
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。
高分辨率纹理 3D 资产生成
Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。
一个具备存储、管理和客户端操作等多种 功能的分布式文件系统相关项目。
3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。