aneterial / laravel-data-validator
Laravel 数据验证和请求注入 DTO 结构的方便包
1.0.1
2024-06-04 22:00 UTC
Requires
- php: >=8.2
- laravel/framework: ^11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.58
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^11.0
README
内容
先决条件
- PHP 8.2 或更高版本
- Laravel 11
开发使用
- PHPUnit &11
- phpstan ^1.11
- php-cs-fixer ^3.58
安装
使用 composer 安装包
composer require aneterial/laravel-data-validator
使用
现在,您有了一个类属性 DataValidator\Attributes\RequestProperty
可以使用。将其添加到 DTO 的属性中,并设置必要的配置字段
use DataValidator\Attributes\RequestProperty; final readonly class ExampleDTO { #[RequestProperty(property: 'id', rules: 'required|integer|min:0')] public int $id; #[RequestProperty(property: 'email', rules: 'required|string|email')] public string $email; }
字段说明
property
:与属性匹配的请求键名rules
:基于组件语义的验证规则 Laravel 验证,接受字符串值requestDataType
:指示字段的位置 - 在请求体中(默认)const RequestProperty::BODY_TYPE
或在查询字符串中const RequestProperty::QUERY_TYPE
listRules
:如果值是数组(列表) - 根据语义设置每个元素的验证规则 Laravel 验证
接下来,您需要在控制器中从应用 DI 容器获取一个 DataValidator\DataManager
实例,并将请求本体传递给它,指明您希望在验证和填充数据后接收的 DTO 类。
$dataManager = app(\DataValidator\DataManager::class);
接下来,Laravel 验证器将检查请求实体(instanse of \Illuminate\Http\Request
),如果数据不正确,将抛出 \Illuminate\Validation\ValidationException
。如果数据正确,Manager 将创建并填充 DTO 对象,您可以在应用程序中使用它
/** @var ExampleDTO $dto */ $dto = $dataManager->validateAndConvert(from: $request, to: ExampleDTO::class);
如果您的端点涉及传递对象数组 [{...}, {...}, {...}]
,您可以使用一个方法来验证请求并返回 DTO 数组
/** @var ExampleDTO[] $dtos */ $dtos = $dataManager->validateAndConvertList(from: $request, to: ExampleDTO::class);
示例
以下是一些使用属性验证的示例
- 具有列表的 DTO
final readonly class ExampleDTO { ... /** @var string[] $emails */ #[RequestProperty(property: 'emails', rules: 'required|list', listRules: 'string|email')] public array $emails; /** @var int[] $ids */ #[RequestProperty(property: 'ids', rules: 'required|list', listRules: 'int|min:0')] public array $ids; ... }
- 具有非必需属性的 DTO,如果不要求则应该是可空的,除了数组 - 它可以是空数组
final readonly class ExampleDTO { #[RequestProperty(property: 'id', rules: 'integer|min:0')] public ?int $id; #[RequestProperty(property: 'email', rules: 'string|email')] public ?string $email; /** @var int[] $ids */ #[RequestProperty(property: 'ids', rules: 'list', listRules: 'int|min:0')] public array $ids; }
- 具有嵌套对象的 DTO
final readonly class ExampleDTO { ... #[RequestProperty(property: 'child', rules: 'required|array')] public NestedDTO $child; ... } // NestedDTO should contain properties with attributes final readonly class NestedDTO { #[RequestProperty(property: 'id', rules: 'required|integer|min:0')] public int $id; #[RequestProperty(property: 'email', rules: 'required|string|email')] public string $email; }
- 具有嵌套对象列表的 DTO
final readonly class ExampleDTO { ... /** @var NestedDTO[] $children */ #[RequestProperty(property: 'children', rules: 'required|list', listRules: NestedDTO::class)] public array $children; ... }
- 具有
BackedEnum
属性枚举的 DTO,您应该将枚举类型设置为属性,无需更多规则,除非您想 - 指明枚举的类型
final readonly class ExampleDTO { ... #[RequestProperty(property: 'enum', rules: 'required|string')] public AnApplicationEnum $enum; ... }
- 具有
BackedEnum
属性枚举的 DTO
final readonly class ExampleDTO { ... /** @var AnApplicationEnum[] $enums */ #[RequestProperty(property: 'enums', rules: 'required|list', listRules: AnApplicationEnum::class)] public array $enums; ... }
限制
- Important note: for different requestDataType
如果 DTO 有嵌套对象或嵌套对象的数组,则忽略这些实体的 requestDataType
,并从父实体获取
所以如果您使用
final readonly class ExampleDTO { ... #[RequestProperty(property: 'child', rules: 'required|array', requestDataType: RequestProperty::BODY_TYPE)] public NestedDTO $child; ... } // NestedDTO should contain properties with attributes final readonly class NestedDTO { #[RequestProperty(property: 'id', rules: 'required|integer|min:0', requestDataType: RequestProperty::QUERY_TYPE)] public int $id; #[RequestProperty(property: 'email', rules: 'required|string|email', requestDataType: RequestProperty::QUERY_TYPE)] public string $email; }
嵌套对象中的 requestDataType
不会工作,它将是 RequestProperty::BODY_TYPE
,就像父实体一样
- Another one: for list validation
DataManager::validateAndConvertList
方法只能与请求体中的数据一起使用,因此在此用法中,实体的所有属性都将强制转换为类型 RequestProperty::BODY_TYPE