source-toad / enhanced-resources
增强 Laravel 的 API 资源。
Requires
- php: ^8.1
- laravel/framework: ^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0|^11.0
This package is auto-updated.
Last update: 2024-09-26 15:14:56 UTC
README
Laravel API 资源的增强。
安装
$ composer require sourcetoad/enhanced-resources
基本用法
要创建一个增强资源,只需扩展 Sourcetoad\EnhancedResources\Resource
而不是 Illuminate\Http\Resources\Json\JsonResource
,并提供一个格式方法。
<?php use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { #[Format] public function foo(): array { return []; } }
格式化
使用 EnhancedResources,您可以为单个资源添加多个格式,只需添加格式方法。格式方法使用 #[Format]
属性定义。
如果只定义了一个格式方法,如上面基本用法部分中的示例,那么该格式将作为默认格式使用,在解析资源时使用。然而,您可以定义任意多个格式。
<?php use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { #[Format] public function bar(): array { return []; } #[Format] public function foo(): array { return []; } #[Format] public function foobar(): array { return []; } }
在上述情况下,您需要通过向 format()
方法提供其名称来指定要使用的格式。默认情况下,格式使用与方法相同的名称,因此在此示例中,我们具有格式名称 bar
、foo
和 foobar
。
ExampleResource::make($object)->format('foo');
在未指定默认格式的情况下,将抛出 NoFormatSelectedException
。
指定默认格式
如果您不想始终显式指定具有多个格式的资源要使用的格式,可以使用 #[IsDefault]
属性指定一个格式作为默认格式。
<?php use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { #[Format] public function bar(): array { return []; } #[IsDefault, Format] public function foo(): array { return []; } #[Format] public function foobar(): array { return []; } }
添加 #[IsDefault]
属性到您的一个格式方法后,除非通过 format()
方法显式指定格式,否则将使用它。
通过 #[IsDefault]
属性指定多个默认方法将抛出 MultipleDefaultFormatsException
。
#[IsDefault]
属性在继承链的每个类上都会被检测,因此您可以在父资源上定义一个 #[IsDefault]
格式,并在子资源上使用另一个 #[IsDefault]
格式来覆盖它,而不会触发 MultipleDefaultFormatsException
。但是,如果子资源上未定义 #[IsDefault]
格式,则仍将使用父资源上的格式。
命名格式
您还可以覆盖格式的名称,甚至为单个格式提供多个名称。让我们看看以下示例
<?php use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { #[Format, Format('a')] public function bar(): array { return []; } #[Format, Format('b'), Format('something-else')] public function foo(): array { return []; } #[Format('c')] public function foobar(): array { return []; } }
在此示例中,我们有三个格式,但有六个名称
bar
方法可以用bar
和a
的名称使用。foo
方法可以用foo
、b
和something-else
的名称使用。foobar
方法可以用c
的名称使用。
每个格式的首选名称是 #[Format]
属性的第一个实例,其余的是别名。这意味着在上面的示例中,首选名称将是 bar
、foo
和 c
。在大多数情况下,这种区别不应发挥作用。
集合
匿名集合和定义的资源集合都利用底层资源对象的格式,并遵循所有相同的规则。
修改
修改允许您动态调整资源的输出。它们的应用方式类似于 Eloquent 工厂中应用 state
的方式。修改的最基本形式是通过向资源的 modify
方法提供一个数组来执行简单的数组合并修改。
ExampleResource::make($object)->modify(['some_key' => 'some_value']);
为了实现更复杂的修改,您还可以传递任何接受(array $data, Resource $resource)
的可调用对象。在使用这些类型的修改时,返回数据非常重要,否则资源的数据将被替换为null
。
ExampleResource::make($object)->modify(function (array $data) { $data['some_key'] = 'some_value'; return $data; })
您还可以在资源类本身上定义方法,通过调用modify
方法来进行修改。
<?php use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { #[Format] public function foo(): array { return [ 'value' => $this->resource['value'], ]; } public function double(): static { return $this->modify(function (array $data) { $data['value'] *= 2; return $data; }); } } ExampleResource::make(['value' => 1])->double()->toArray(); // ['value' => 2]
除了...
异常增强是一个修改类和特性的组合,允许轻松地从资源中排除某些字段。
<?php use Sourcetoad\EnhancedResources\Enhancements\Except; use Sourcetoad\EnhancedResources\Enhancements\Traits\HasExceptEnhancement; use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { use HasExceptEnhancement; #[Format] public function foo(): array { return [ 'first_name' => $this->resource->firstName, 'id' => $this->resource->id, 'last_name' => $this->resource->lastName, ]; } } ExampleResource::make(new class { public string $firstName = 'John'; public int $id = 1; public string $lastName = 'Doe'; })->except('id'); // ['first_name' => 'John', 'last_name' => 'Doe'] // Without the trait you can still use the Except enhancement. ExampleResource::make(new class { public string $firstName = 'John'; public int $id = 1; public string $lastName = 'Doe'; })->modify(new Except(['id'])); // ['first_name' => 'John', 'last_name' => 'Doe']
仅...
仅增强是一个修改类和特性的组合,允许轻松地从资源中排除某些字段。
<?php use Sourcetoad\EnhancedResources\Enhancements\Only; use Sourcetoad\EnhancedResources\Enhancements\Traits\HasOnlyEnhancement; use Sourcetoad\EnhancedResources\Formatting\Attributes\Format; use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault; use Sourcetoad\EnhancedResources\Resource; class ExampleResource extends Resource { use HasOnlyEnhancement; #[Format] public function foo(): array { return [ 'first_name' => $this->resource->firstName, 'id' => $this->resource->id, 'last_name' => $this->resource->lastName, ]; } } ExampleResource::make(new class { public string $firstName = 'John'; public int $id = 1; public string $lastName = 'Doe'; })->only('id'); // ['id' => 1] // Without the trait you can still use the Only enhancement. ExampleResource::make(new class { public string $firstName = 'John'; public int $id = 1; public string $lastName = 'Doe'; })->modify(new Only(['id'])); // ['id' => 1]
其他增强
EnhancedResources还包括一些其他有用的增强。
状态码
现在,您可以通过调用setResponseStatus()
方法简单地调整资源响应的状态码。
use Symfony\Component\HttpFoundation\Response; ExampleResource::make($object)->setResponseStatus(Response::HTTP_I_AM_A_TEAPOT);
ConvertsToResource
您可以通过简单的特性和属性组合为任何具有toResource
方法的对象提供。
use Illuminate\Database\Eloquent\Model; use Sourcetoad\EnhancedResources\Resourceable\AsResource; use Sourcetoad\EnhancedResources\Resourceable\ConvertsToResource; /** * @method ExampleResource toResource() */ #[AsResource(ExampleResource::class)] class Example extends Model { use ConvertsToResource; } (new Example)->toResource();
测试
建议使用Laravel现有的响应断言来测试返回增强资源的端点。一种创建资源断言对象的方法,该方法利用了增强资源提供的功能,可以在以下链接中找到:这里。