rmezhuev/data-transfer-object

基于 PHP 注释的简单且简单的不可变 DTO 模式实现

v1.2.0 2024-06-05 10:38 UTC

This package is auto-updated.

Last update: 2024-09-05 11:14:21 UTC


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\ArrayableIlluminate\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)。请参阅许可证获取更多信息。