phpexperts/simple-dto

一个快速简单的DTO包。

v3.7.1.1 2024-07-31 02:15 UTC

README

TravisCI Maintainability Test Coverage

SimpleDTO是PHP Experts,Inc.的项目,旨在简化数据传输对象(DTO)的使用。

基本上,DTO上的任何受保护属性都可以设置为通过构造函数传入的数组元素,或者作为属性本身的默认值。

DTO是不可变的:一旦创建,就不能更改。请创建一个新的对象。

安装

通过Composer

composer require phpexperts/simple-dto

使用

从版本2开始,您必须为每个属性定义类级别的@property docblocks。

您还必须定义数据类型。

use Carbon\Carbon;
use PHPExperts\SimpleDTO\SimpleDTO;

/**
 * @property-read string $name
 * @property-read Carbon $date
 */
class BirthdayDTO extends SimpleDTO
{
    /** @var string */
    protected $name;
    
    /** @var Carbon */
    protected $date;
}

$birthdayDTO = new BirthdayDTO([
    'name' => 'Donald J. Trump',
    'date' => '1946-06-14',
]);

// Access as a property:
echo $birthday->name; // Donald J. Trump

// Properties with the data type of "Carbon" or "Carbon\Carbon" 
// are automagically converted to Carbon objects.
echo $birthday->date->format('F jS, Y'); // June 14th, 1946

// Easily output as an array:
$birthday->toArray();

// Copy from one to another:
$newDTO = new BirthdayDTO($birthdayDTO->toArray());

// Copy from one to another, with new properties:
$newDTO = new BirthdayDTO($birthdayDTO->toArray() + [
    'date' => '2020-11-03',
]);

// Easily output as JSON:
echo json_encode($birthdayDTO);
/* Output: 
{
    "name": "Donald J. Trump",
    "date": "1946-06-14T00:00:00.000000Z"
}
*/

模糊数据类型

但如果你还没有准备好/能够深入了解严格的PHP数据类型呢?

那么,就这样实例化父类

    use PHPExperts\DataTypeValidator\DataTypeValidator;
    use PHPExperts\DataTypeValidator\IsAFuzzyDataType;
    
    /**
     * @property int   $daysAlive
     * @property float $age
     * @property bool  $isHappy
     */
    class MyFuzzyDTO extends SimpleDTO
    {
        public function __construct(array $input)
        {
            parent::__construct($input, new DataTypeValidator(new IsAFuzzyDataType());
        }
    }

    $person = new MyFuzzyDTO([
        'daysAlive' => '5000',
        'age'       => '13.689',
        'isHappy'   => 1,
    ]);

    echo json_encode($person, JSON_PRETTY_PRINT);
    /*
    {
        "daysAlive": "5000",
        "age": "13.689",
        "isHappy": 1
    }
    */

一次写入的DTO

有时,你可能需要在创建DTO后初始化一个或多个值。这在某些API(尤其是Zuora的)通过多次往返进行状态管理时尤其常见。

为了克服传统数据类型对象的不可变性质,你可以使用WriteOnce特质。

这将使您能够使用null未初始化的属性初始化DTO,并只设置一次。

此外,您必须在序列化或json_encode()对象、发送到toArray()等之前设置每个属性。

/**
* @property string $name
*/
class CityDTO extends SimpleDTO
{
    use WriteOnce;

    protected int $population;
}

$cityDTO = new CityDTO(['name' => 'Dubai']);
dd($cityDTO);

忽略某些受保护属性。

如果你使用的是PHP 8.0或更高版本,你可以使用SimpleDTO通过#[IgnoreAsDTO]属性忽略任何特定的protected属性(PHP将将其视为任何常规受保护属性)。

$testDTO = new class(['name' => 'Sofia', 'birthYear' => 2010]) extends SimpleDTO {
    #[IgnoreAsDTO]
    protected int $age;

    protected string $name;
    protected int $birthYear;

    public function calcAge(): int
    {
        $this->age = date('Y') - $this->birthYear;

        return $this->age;
    }
};

嵌套DTO

您可以在DTO内部嵌套DTO。

    $myDTO = new MyTestDTO([
        'name' => 'PHP Experts, Inc.',
        'age'  => 7.01,
        'year' => 2019,
    ]);

    /**
     * @property MyTestDTO $myDTO
     */
    $dto = new class(['myDTO' => $myDTO]) extends NestedDTO
    {
    };
    
    /*
    PHPExperts\SimpleDTO\NestedDTO@anonymous {
      -dataTypeRules: array:1 [
        "myDTO" => "?MyTestDTO"
      ]
      -data: array:1 [
        "myDTO" => PHPExperts\SimpleDTO\Tests\MyTestDTO {#355
          -dataTypeRules: array:3 [
            "name" => "?string"
            "age" => "?float"
            "year" => "?int"
          ]
          -data: array:3 [
            "name" => "PHP Experts, Inc."
            "age" => 7.01
            "year" => 2019
          ]
        }
      ]
    }
    */

用例

PHPExperts\SimpleDTO\SimpleDTO
✔ 属性通过构造函数设置
✔ 属性作为公共属性访问
✔ 构造函数为类型属性分配默认值
✔ 公共、私有和静态受保护属性将被忽略
✔ 每个DTO都是不可变的
✔ 设置任何属性都会抛出异常
✔ 可以使用具体属性设置默认值
✔ 类型为carbon的属性变为carbon日期
✔ 可以轻松输出到数组
✔ 可以轻松JSON编码
✔ 可以轻松JSON解码
✔ 允许空值属性
✔ 在宽容模式下,每个属性都是可空的
✔ 可以序列化
✔ 可以反序列化
✔ 可以添加额外的验证
✔ 可以获取内部数据
✔ 可以确定是否宽容
✔ 可以使用#[IgnoreDTO]属性忽略受保护属性

PHPExperts\SimpleDTO\NestedDTO
✔ 将构建嵌套DTO
✔ 可以构建嵌套DTO数组
✔ 可以检索存储的DTO
✔ 将数组数据转换为适当的嵌套DTO
✔ 将stdClasses转换为适当的嵌套DTO
✔ 嵌套DTO使用松散类型
✔ 可以使用类型属性构建嵌套DTO
✔ 使用类型属性的嵌套DTO使用严格类型
✔ 所有注册的嵌套DTO都是必需的
✔ 可选的、未注册的嵌套DTO将被优雅地处理
✔ 可以序列化
✔ 可以反序列化
✔ 可以手动验证DTO
✔ 可以获取内部数据

PHPExperts\SimpleDTO\WriteOnceTrait
✔ 可以接受null值
✔ 可以序列化
✔ 将在序列化时进行验证
✔ 将验证到数组
✔ 可写一次null值
✔ 只写一次的值必须验证

SimpleDTO 错误路径
✔ 不能使用不存在的属性初始化
✔ 访问不存在的属性会抛出错误
✔ DTO 必须有类属性 docblocks 或为每个具体属性提供类型提示
✔ 碳日期字符串必须是可解析的日期
✔ 属性必须与它们的数据类型匹配
✔ 不会反序列化包含无效数据的 DTO
✔ 不能覆盖不存在的属性

测试

phpunit --testdox

贡献者

Theodore R. Smith theodore@phpexperts.pro
GPG 指纹: 4BF8 2613 1C34 87AC D28F 2AD8 EB24 A91D D612 5690
首席执行官:PHP Experts, Inc.

许可

MIT 许可证。有关更多信息,请参阅许可证文件