JSON:API Resource这是一个轻量级的 Laravel API 资源包,可帮助你遵循 JSON:API 标准,内置支持稀疏字段集、复合文档等功能。
注意 这些文档并非旨在介绍
JSON:API规范及相关概念,如果你还不熟悉,应该前往阅读规范。以下文档仅涵盖如何通过该包来实现规范。
目录
8.1, 8.2, 8.39.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


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频


实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号