klkvsk / dto-generator
使用零运行时依赖生成 DTO 类
Requires
- php: >=8.1
- nette/php-generator: ^4.0
- opis/closure: ^3.6
- psr/log: ^3.0
- spatie/php-cloneable: ^1.0.1
- splitbrain/php-cli: ^1.2
- ulrichsg/getopt-php: ^4.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.14
- phpunit/phpunit: ^10.0
- vimeo/psalm: ^5.7
README
使用零运行时依赖生成 DTO 类
此包允许您通过简短的 PHP 代码声明模式来生成干净、独立的 DTO 类(也称为 "值对象")。
安装
您只需要在开发环境中使用此包,因为生成的类不使用此库的任何代码。这就是为什么首选的方式是将它包含在 require-dev
中。
$ composer require --dev klkvsk/dto-generator
要求
- PHP 8.1+:在开发中运行生成器
- PHP 7.4 或 8.x:在生产中使用生成的代码
用法
1. 创建模式文件
模式是一个常规 PHP 文件,位于项目中的任何位置。该文件应从顶层返回一个 Schema
对象。
示例模式
<?php use Klkvsk\DtoGenerator\Schema as dto; use Klkvsk\DtoGenerator\Schema\Types as t; return dto\schema( namespace: 'MyProject\Data', objects: [ new dto\object( name: 'Person', fields: [ dto\field('name', t\string(), required: true), dto\field('age', t\int(), required: true), ] ), ] );
2. 生成文件
使用 dto-gen
命令进行代码生成
$ ./vendor/bin/dto-gen [schema-file]
默认情况下,生成器会搜索名为或以 dto.schema.php
结尾的文件,但您可以通过参数手动提供模式文件。
生成器会尝试通过查看 composer.json 中的自动加载路径来猜测正确的输出路径。如果它声明了 "MyProject\\": "src/"
的 PSR-4 映射,那么上面的文件将放置在 src/Data/Person.php
。
要覆盖此行为,您可以直接指定 outputDir
。
dto\schema(namespace: "MyProject\\Data", outputDir: "src/generated/", ...);
特性
向后兼容
要生成针对某些 PHP 最小版本的代码,请使用
./vendor/bin/dto-gen --target 7.4
此选项启用或禁用结果代码中的一些较新语言功能。
枚举
您不仅可以生成 DTO,还可以生成相关的枚举
dto\schema( objects: [ dto\enum( name: 'PostStatus' cases: [ 'draft', 'published', 'deleted' ] ), dto\object( name: 'Post', fields: [ dto\field('status', t\enum('PostStatus'), required: true), ... ] ) ] )
对于 PHP >= 8.0,将生成原生枚举,对于旧版本,将使用非常类似类实现的类。
类型系统
DTO 用于保持数据类型的安全。模式的类型有
t\int
,t\bool
,t\string
,t\float
- 基本标量类型t\enum
,t\object
- 用于引用其他 DTO 对象t\date
- 使用 DateTimeImmutablet\external
- 用于引用任何其他非 DTO 类t\list_(T)
- 将类型 T 包装起来以声明 T[]t\mixed
- 如果您真的不知道
(其中 t
是 Klkvsk\DtoGenerator\Schema\Types
的别名)
此外,您可以根据需要扩展抽象 Type
类。
填充和验证
DTO 可以使用常规构造函数或使用 <DTO>::create(array $data)
方法创建。
create
方法接受一个包含数据的关联数组。然后,该数据被 过滤(如果需要事先进行一些清理)并 导入(转换为适当的类型)。之后,该方法调用默认构造函数,并将导入的字段传递给它。构造函数不仅通过类型,还通过自定义逻辑来 验证 字段。
因此,数据操作有三个阶段,每个阶段都可以在模式中使用可调用函数进行描述
filter
准备要导入的数据importer
将值转换为正确的类型或实例化嵌套对象validator
检查导入的值是否符合指定的标准
filter
和 importer
闭包应返回处理过的值。如果返回 null
,则不会调用其他闭包。
validator
返回 true/false,如果返回 false,则自动抛出 InvalidArgumentException
。您还可以抛出自定义异常而不返回任何内容。
filter
和 validator
类型的闭包在模式中定义
dto\field('age', t\int(),
filters: [ fn ($x) => preg_replace('/[^0-9]+/', $x) ],
validators: [ fn ($x) => $x > 0 && $x < 100 ]
)
importer
闭包对所有类型都预定义,除了 t\object
。
dto\field('file', t\external(SplFileInfo::class, fn ($x) => new SplFileInfo($x))
如果您为自定义需要扩展 Type
,则可以指定自定义导入器。
示例
请参阅 /example/ 目录以获取示例架构和不同PHP版本的生成类。
许可证
MIT许可证(MIT)。有关更多信息,请参阅 许可证文件。