Laravel 中的 JSON API 资源
发布日期:作者: Steve McDougall
在 Laravel 中构建 API 是我的爱好,我花了大量时间寻找返回一致的 JSON:API 友好资源的完美方法,以便我能找到和使用一个标准。
过去,我使用过一个拼凑起来的解决方案,它几乎可以实现我需要的功能,但它需要相当多的工作。这种方法的缺点超过了它的优点,因为实现它所花费的开发时间感觉不值得。
幸运的是,对于你和我的好处,Tim MacDonald 为此用例构建了一个很棒的软件包。它允许我们构建并返回符合 JSON:API 标准的资源,这些资源易于使用。让我们来了解它的工作原理。
通常在构建 API 资源时,我们会扩展 Laravels 的 JsonResource
或 CollectionResource
,具体取决于我们想要实现的目标。我们的典型资源可能如下所示
class PostResource extends JsonResource{ public function toArray($request): array { return [ 'id' => $this->id, 'type' => 'post', 'attributes' => [ 'title' => $this->title, 'slug' => $this->slug, 'content' => $this->content, ] ]; }}
我们添加了一个简单的实现来在基本级别“伪造”JSON:API 资源。但正如您所见,这有点糟糕。让我们安装 Tim 的软件包
composer require timacdonald/json-api
现在我们可以重构上面的资源以遵循 JSON:API 标准。让我带您了解更改过程。
首先,我们需要将我们扩展的类从 JsonResource
更改为 JsonApiResource
class PostResource extends JsonApiResource
我们需要确保更改的下一件事是删除 toArray
方法,因为该软件包将在幕后为您处理此操作 - 相反,我们使用对 JSON:API 标准有用的不同方法。例如,要将 attributes
添加到您的资源,可以使用以下方法
protected function toAttributes(Request $request): array{ return [ 'title' => $this->title, 'slug' => $this->slug, 'content' => $this->content, ];}
现在让我们看一下关系。以前我们会做类似的事情
return [ 'id' => $this->id, 'type' => 'post', 'attributes' => [ 'title' => $this->title, 'slug' => $this->slug, 'content' => $this->content, ], 'relationships' => [ 'category' => new CategoryResource( resource: $this->whenLoaded('category'), ), ]];
这绝不是一种糟糕的方法;但是,让我们看看如何在 JSON:API 软件包中添加这些内容
protected function toRelationships(Request $request): array{ return [ 'category' => fn () => new CategoryResource( resource: $this->category, ), ];}
所以这一次,我们传递一个闭包以进行评估以返回关系。这是一种非常强大的方法,因为它使我们可以为关系加载添加非常自定义的行为 - 意味着我们可以加载不同的条件关系或在资源上运行授权。另一个需要注意的点是,闭包仅在客户端包含关系时才被评估 - 使它更简洁。
更进一步,将链接添加到您的 API 资源是我认为很重要的一步。添加这些链接使您的 API 可导航,允许客户端按需以编程方式遵循链接。以前我会添加另一个数组条目来添加这些链接并使用 route
助手来回显它们。JSON:API 软件包有一个替代方法,它非常流畅
protected function toLinks(Request $request): array{ return [ Link::self(route('api:v1:posts:show', $this->resource)), ];}
正如您所见 - 它流畅、简单,并且会为您生成正确的链接。当然,欢迎您在此处添加所需的内容,但它将以 JSON:API 标准化方式添加链接 - 所以您不必这样做。
最后,元数据,在 JSON:API 中,您可以在 meta-object
中添加其他信息,以便您可以添加文档链接或您可能需要与 API 资源一起传递的任何内容(取决于您的 API 设计)。这并没有很多用例,但该软件包确实支持它。所以让我们看一下它来理解它。
protected function toMeta(Request $request): array{ return [ 'depreciated' => false, 'docs' => 'https://docs.domain/com/resources/posts', ];}
如您在上面所见,我们可以添加弃用警告,以便客户端可以收到有关需要考虑更改的资源的通知 - 以及解释替代方法的文档链接。
您是如何构建您的 API 资源的?您是否遵循任何特定标准?请在 Twitter 上告诉我们!