larsmbergvall / json-api-resources-for-laravel
为Laravel提供的简单JSON:API资源包
Requires
- php: ^8.1|^8.2
- illuminate/contracts: ^9.34|^10.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
- spatie/laravel-ray: ^1.32
This package is auto-updated.
Last update: 2024-09-10 00:53:40 UTC
README
目录
示例
这是此包生成的输出示例
public function books() { $books = Book::with(['author.country'])->take(2)->get(); return JsonApiResourceCollection::make($books)->withIncluded(); }
返回此内容
{ "data": [ { "id": "1", "type": "books", "attributes": { "title": "Dolores Dolor Totam", "year": 1871 }, "relationships": { "author": { "data": { "id": "1", "type": "author" } } }, "links": {}, "meta": {} }, { "id": "2", "type": "books", "attributes": { "title": "Velit Quo Omnis", "year": 1969 }, "relationships": { "author": { "data": { "id": "2", "type": "author" } } }, "links": {}, "meta": {} } ], "included": [ { "id": "1", "type": "author", "attributes": { "name": "Rylee Heller DDS", "country_id": 18, "bio": "Non iusto porro maxime. Quibusdam provident architecto magni sed id et. Voluptatem sint a numquam eius omnis aut.\n\nVoluptas quis voluptatem et fuga aspernatur eaque. Necessitatibus possimus iure corporis et quasi cum. Blanditiis quis sapiente ut dolores. Dolorem odio et quas aut et nihil qui.\n\nAut quod sint numquam. Ullam id odio velit neque non. Aut recusandae sint explicabo ut veritatis aliquid harum.", "born_at": "1986-10-22 08:00:02", "created_at": "2023-03-09 12:55:20", "updated_at": "2023-03-09 12:55:20" }, "relationships": {}, "links": {}, "meta": {} }, { "id": "2", "type": "author", "attributes": { "name": "Ms. Rosella Quigley Sr.", "country_id": 12, "bio": "Architecto voluptas nobis sed. Ea qui quas voluptatem est nisi. Voluptatem et quis ut asperiores fuga autem blanditiis repellendus. Qui non sapiente esse quasi corporis fugit ut aut.\n\nDolorem id dolore quis qui ullam dolorem. Qui voluptatibus quia reprehenderit dolor aut est corrupti. Debitis debitis cum vitae nam quis fugit nemo. Quia labore et delectus est qui.\n\nNumquam accusantium et in. Non tenetur iure explicabo expedita sint. Quam sit qui doloremque asperiores ducimus impedit enim. In recusandae et cumque nisi ea laudantium in.", "born_at": "1996-08-07 13:15:36", "created_at": "2023-03-09 12:55:20", "updated_at": "2023-03-09 12:55:20" }, "relationships": {}, "links": {}, "meta": {} } ] }
安装
您可以通过composer安装此包
composer require larsmbergvall/json-api-resources-for-laravel
建议您使用中间件,要么对所有API调用
// ./app/Http/Kernel.php protected $middlewareGroups = [ // ... // Web middleware and such // ... 'api' => [ // Other api middlewares JsonApiMiddleware::class, ], ]
或者,基于每个路由
// ./routes/api.php Route::prefix('/v1') ->middleware(JsonApiMiddleware::class) ->group(function () { // Api v1 routes });
使用
属性
此包使用PHP 8属性来注释Eloquent模型。不需要额外的资源类。属性的使用方式如下
use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiIncludeAttributes; use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiIncludeRelationships; use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiType; #[JsonApiType('books')] // Change `type` property #[JsonApiIncludeAttributes(['title', 'isbn', 'year'])] // Which of the models attributes to include // Which of the models relationships to include. // NOTE: it only includes eager loaded relationships regardless of this attribute #[JsonApiIncludeRelationships(['author'])] class Book extends Model { // ... }
#[JsonApiType(string)]
此属性可以用来更改最终输出JSON中的type
属性的值。此属性是可选的。如果没有使用,则将type
设置为模型名称的单数形式,即'type' => 'book'
。
#[JsonApiIncludeAttributes(string[])]
此属性可以用来指定哪些模型属性应该包含在最终的输出JSON中。此属性是可选的。如果没有使用,则将包含所有可见的模型属性。它使用$model->attributesToArray()
来获取属性,因此将尊重任何$hidden
字段。
#[JsonApiIncludeRelationships(string[])]
此属性可以用来指定哪些模型关系应该包含在内。此属性是可选的。如果没有使用,则不会在最终的输出JSON中包含任何关系。
注意:无论此属性包含什么,JsonApiResource
只包含懒加载的关系。
创建JsonApiResources
如果您有一个单个模型,应使用JsonApiResource
use Larsmbergvall\JsonApiResourcesForLaravel\JsonApi\JsonApiResource; public function show(Book $book): JsonApiResource { return JsonApiResource::make($book); }
如果您有一组模型,应使用JsonApiResourceCollection
use Larsmbergvall\JsonApiResourcesForLaravel\JsonApi\JsonApiResourceCollection; public function index(): JsonApiResource { // Can also be used with pagination: // return JsonApiResourceCollection::make(Book::orderBy('title')->paginate()); return JsonApiResourceCollection::make(Book::all()); }
如果您需要手动返回JSON:API响应,或者不想使用中间件,可以使用jsonApiResponse()
辅助函数
// return jsonApiResponse(JsonApiResource::make($book)); return jsonApiResponse($content, $status, $headers)
它设置了JSON:API响应的正确Content-Type
头。请注意,它不会转换验证错误。
中间件
中间件主要处理两件事
- 确保返回的响应具有正确的头等。
- 将Laravel的验证错误转换为预期的JSON:API错误格式
中间件应该在可能更改响应的Content-Type
头的其他中间件之后执行。
JsonApiResource类
此类有几个公开方法,您可以使用。您很可能不需要这样做,因为JsonApiResourceCollection
类会自动处理这些。
但是,有一个重要的方法:withIncluded()
。默认情况下,JsonApiResource
不包含相关数据。但是,如果您运行$resource->withIncluded()
(或JsonApiResource::make($book)->withIncluded())
,它就会这样做。
注意:它只包含懒加载的关系,因此如果您需要为某个API路由排除某些内容,只需选择不加载关系即可。但是,它会递归地包含相关数据,这意味着它还会包含包含数据的关联数据。
JsonApiResourceCollection类
该类还包含一个withIncluded()
方法,您可以使用它将任何相关数据包含到资源中。与JsonApiResource
一样,它仅包含已加载的关联关系。然而,它会递归地包含相关数据,这意味着它还会包含与包含数据相关的数据。
错误转换
当Laravel中的验证失败时,通常您会得到如下所示的响应
{ "message": "The data.attributes.foo field is required.", "errors": { "data.attributes.foo": [ "The data.attributes.foo field is required." ] } }
但是,使用JsonApiMiddleware后,此响应将变为
{ "errors": [ { "status": "422", "title": "Unprocessable Content", "detail": "The data.attributes.foo field is required.", "source": { "pointer": "data/attributes/foo", "parameter": "foo" } } ] }
测试
JsonApiResource
和JsonApiResourceCollection
类中提供了一些测试工具,您可以使用它们来测试您的应用程序。
注意,未来版本还将提供更多测试工具!
assertHasData
$author = Author::factory()->create(); $resource = JsonApiResource::make($author); $id = $author->id; $type = 'author'; $resource->assertHasData($id, $type);
assertDoesntHaveData
$author = Author::factory()->create(); $resource = JsonApiResourceCollection::make(collect([$author])); $id = $author->id + 999; $type = 'author'; $resource->assertDoesntHave($id, $type);
这是assertHasData
的相反。如果它找到了预期的数据,则会失败。
变更日志
请参阅变更日志以获取有关最近更改的更多信息。
致谢
- Lars Bergvall
- 所有贡献者
- Spatie提供的惊人的Laravel包骨架
许可
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。