rmezhuev/ data-transfer-object
基于 PHP 注释的简单且简单的不可变 DTO 模式实现
Requires
- php: ^8.0
- ext-json: *
- illuminate/support: ^5.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.00
- phpdocumentor/reflection-docblock: ^5.3
- symfony/property-info: ^4.0|^5.0|^6.0|7.0
Requires (Dev)
- fakerphp/faker: ^1.9.1
- phpunit/phpunit: ^8.5
- symfony/var-dumper: ^5.0
README
实现不可变数据传输对象 (DTO) 概念,以安全地在应用程序架构层之间传输数据。例如,将来自 API 的数据传输到应用程序核心。数组由于缺乏严格的结构、验证、类型检查和不可变性,因此不提供可靠的方法来完成此目的。数据传输对象 (DTO) 可以解决这个问题,同时保持一个简单的数据结构对象,不包含业务逻辑,同时提供强大的工具来验证、结构化和序列化数据。
安装
您可以通过 composer 安装此包
composer require rmezhuev/data-transfer-object
使用方法
声明
该包包含 RMezhuev\DTO\DataObject
类,要创建自己的 DTO,只需从该类扩展即可。
use RMezhuev\DTO\DataObject; /** * @property string $name * @property string $email * @property string|int|null $age * @property array|null $phone * @property CustomType|null $details */ class PersonDto extends DataObject { }
为了使类对 IDE
友好且不可变,使用 phpdoc
声明支持属性。所有属性和值在对象构造时都会进行验证。对于可选属性,必须在类型的描述中添加 null
。
初始化
构造函数
对象的构造函数期望一个属性关联数组,其名称与 phpdoc
名称匹配,其值支持类型。
$personDto = new PersonDto([ 'email' =>'john.doe@gmail.com', 'name' => 'John Doe', 'age' => 35, ]);
工厂方法
您可能需要根据使用上下文从不同的数据结构初始化您的 DTO。为此,您可以为每个特定情况使用单独的工厂方法。
class PersonDto extends DataObject { public static function fromRequest(Request $request): self { return new self( $request->only([ 'email', 'name', ]) ); } public static function fromApi(array $data): self { return new self([ 'email' => $data['primary_email'], 'name' => $data['full_name'], ]); } }
访问数据
通过魔法获取器或数组表示法
所有属性都可以通过在基类中定义的魔法获取器访问。您还可以使用数组括号表示法,因为该类还实现了 Arrayable
接口。
$personDto = new PersonDto([ 'name' => 'John Doe', 'email' =>'john.doe@gmail.com', ]); echo($personDto->name); //John Doe echo($personDto->email); //john.doe@gmail.com echo($personDto['name']); //John Doe echo($personDto['email']); //john.doe@gmail.com
序列化
DTO 支持开箱即用的 toArray()
和 toJson()
序列化,并实现了相应的接口 Illuminate\Contracts\Support\Arrayable
和 Illuminate\Contracts\Support\Jsonable
,以更好地与 Laravel
框架集成。
蛇形命名
默认情况下,在序列化期间,所有名称都将转换为蛇形命名,因此 fullName
将变为 full_name
。要禁用此行为,可以将 $snakeOnSerialize = false
。
class PersonDto extends DataObject { protected $snakeOnSerialize = false; }
部分模式
在序列化时,DTO 允许您指定 partial
模式。在这种情况下,仅序列化隐式初始化的字段,其余所有字段都将被排除。此模式对于部分更新很有用,当您需要区分 nullable
字段是否隐式设置为 null
值或根本未设置时。
$personDto = new PersonDto([ 'name' => 'John Doe', 'email' =>'john.doe@gmail.com', ]); $personDto->toArray(); // Result: // [ // "name" => "John Doe" // "email" => "john.doe@gmail.com" // "age" => null // "phone" => null // "details" => null // ] $personDto->partial()->toArray(); // Result: // [ // "name" => "John Doe" // "email" => "john.doe@gmail.com" // ]
自定义序列化
当内置方法不符合您的需求或您想使其更加明确时,可以在子类中轻松重写序列化方法。
class PersonDto extends DataObject { public static function toArray(): array { return [ 'full_name' => $this->name, 'email' => $this->email, 'year' => date("Y") - $this->age ]; } }
异常处理
除了属性类型验证外,在构造数据传输对象时,还将检查是否设置了所有必需的属性。如果没有,则将抛出 RMezhuev\DTO\Exceptions\DataObjectException
。同样,如果您尝试设置不支持的或更改现有属性,您将获得相同的异常。
测试
composer test
更新日志
请参阅 更新日志 了解最近更改的更多信息。
许可
MIT许可证(MIT)。请参阅许可证获取更多信息。