spatie / value-object
Requires
- php: ^8.0
Requires (Dev)
- illuminate/collections: ^8.36
- jetbrains/phpstorm-attributes: ^1.0
- larapack/dd: ^1.1
- phpunit/phpunit: ^9.5.5
- dev-main
- v4.x-dev
- 3.9.1
- 3.9.0
- 3.8.1
- 3.8.0
- 3.7.3
- 3.7.2
- 3.7.1
- 3.7.0
- 3.6.2
- 3.6.1
- 3.6.0
- 3.5.0
- 3.4.0
- 3.3.0
- 3.2.0
- 3.1.1
- 3.1.0
- 3.0.4
- 3.0.3
- 3.0.2
- 3.0.1
- 3.0.0
- v2.x-dev
- 2.8.4
- 2.8.3
- 2.8.2
- 2.8.1
- 2.8.0
- 2.7.0
- 2.6.0
- 2.5.0
- 2.4.0
- 2.3.0
- 2.2.1
- 2.2.0
- 2.1.0
- 2.0.0
- v1.x-dev
- 1.14.1
- 1.14.0
- 1.13.3
- 1.13.2
- 1.13.1
- 1.13.0
- 1.12.0
- 1.11.0
- 1.10.0
- 1.9.1
- 1.9.0
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.6
- 1.6.5
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.0
- 0.1.0
- 0.0.1
- dev-nested-validation
This package is auto-updated.
Last update: 2022-11-01 08:48:45 UTC
README
警告 我们 已经决定 停止维护此包。
考虑迁移到 spatie/laravel-data 或 cuyz/valinor。
请随意分支我们的代码并适应您的需求。
内置电池的数据传输对象
安装
您可以通过 composer 安装此包
composer require spatie/data-transfer-object
- 注意:此包的 v3 版本仅支持
php:^8.0
。如果您需要旧版本,请查看 v2。
支持我们
我们投入了大量资源来创建 最佳开源包。您可以通过 购买我们的付费产品 来支持我们。
我们非常感谢您从家乡寄来明信片,说明您正在使用我们的哪个包。您可以在 我们的联系页面 上找到我们的地址。我们将发布所有收到的明信片在我们的 虚拟明信片墙 上。
使用
此包的目的是使从数组(序列化)数据构建对象尽可能简单。以下是一个 DTO 的样子
use Spatie\DataTransferObject\Attributes\MapFrom; use Spatie\DataTransferObject\DataTransferObject; class MyDTO extends DataTransferObject { public OtherDTO $otherDTO; public OtherDTOCollection $collection; #[CastWith(ComplexObjectCaster::class)] public ComplexObject $complexObject; public ComplexObjectWithCast $complexObjectWithCast; #[NumberBetween(1, 100)] public int $a; #[MapFrom('address.city')] public string $city; }
您可以这样构建此 DTO
$dto = new MyDTO( a: 5, collection: [ ['id' => 1], ['id' => 2], ['id' => 3], ], complexObject: [ 'name' => 'test', ], complexObjectWithCast: [ 'name' => 'test', ], otherDTO: ['id' => 5], );
让我们逐一讨论所有可能性。
命名参数
可以使用命名参数来构建 DTO。也可以继续使用旧的数组表示法。此示例与上面的示例等效。
$dto = new MyDTO([ 'a' => 5, 'collection' => [ ['id' => 1], ['id' => 2], ['id' => 3], ], 'complexObject' => [ 'name' => 'test', ], 'complexObjectWithCast' => [ 'name' => 'test', ], 'otherDTO' => ['id' => 5], ]);
值转换
如果 DTO 有一个属性是另一个 DTO 或 DTO 集合,则包会自动将数据数组转换为这些 DTO。
$dto = new MyDTO( collection: [ // This will become an object of class OtherDTOCollection ['id' => 1], ['id' => 2], // Each item will be an instance of OtherDTO ['id' => 3], ], otherDTO: ['id' => 5], // This data will be cast to OtherDTO );
自定义转换器
您可以构建自己的转换器类,这些类将接受任何输入,并将输入转换为所需的结果。
看看 ComplexObject
class ComplexObject { public string $name; }
及其转换器 ComplexObjectCaster
use Spatie\DataTransferObject\Caster; class ComplexObjectCaster implements Caster { /** * @param array|mixed $value * * @return mixed */ public function cast(mixed $value): ComplexObject { return new ComplexObject( name: $value['name'] ); } }
类特定转换器
您也可以在目标类本身上定义转换器,而不仅仅是为每个属性指定应使用的转换器。
class MyDTO extends DataTransferObject { public ComplexObjectWithCast $complexObjectWithCast; }
#[CastWith(ComplexObjectWithCastCaster::class)] class ComplexObjectWithCast { public string $name; }
默认转换器
可以在DTO类本身上定义默认的转换器。当在DTO类中遇到具有给定类型的属性时,将使用这些转换器。
#[ DefaultCast(DateTimeImmutable::class, DateTimeImmutableCaster::class), DefaultCast(MyEnum::class, EnumCaster::class), ] abstract class BaseDataTransferObject extends DataTransferObject { public MyEnum $status; // EnumCaster will be used public DateTimeImmutable $date; // DateTimeImmutableCaster will be used }
使用自定义转换器参数
任何转换器都可以传递自定义参数,内置的 ArrayCaster
实现 是如何使用此功能的良好示例。
在向您的转换器传递输入时使用命名参数可以使您的代码更加清晰,但它们不是必需的。
例如
/** @var \Spatie\DataTransferObject\Tests\Foo[] */ #[CastWith(ArrayCaster::class, itemType: Foo::class)] public array $collectionWithNamedArguments; /** @var \Spatie\DataTransferObject\Tests\Foo[] */ #[CastWith(ArrayCaster::class, Foo::class)] public array $collectionWithoutNamedArguments;
请注意,传递给转换器构造函数的第一个参数始终是要转换的值的类型(类型)数组。所有其他参数都将是作为 CastWith
属性中的额外参数传递的参数。
验证
此包不提供任何特定的验证功能,但它确实提供了一种方法来构建自己的验证属性。例如,NumberBetween
是用户实现的验证属性
class MyDTO extends DataTransferObject { #[NumberBetween(1, 100)] public int $a; }
它在底层是这样工作的
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] class NumberBetween implements Validator { public function __construct( private int $min, private int $max ) { } public function validate(mixed $value): ValidationResult { if ($value < $this->min) { return ValidationResult::invalid("Value should be greater than or equal to {$this->min}"); } if ($value > $this->max) { return ValidationResult::invalid("Value should be less than or equal to {$this->max}"); } return ValidationResult::valid(); } }
映射
您可以使用 #[MapFrom]
属性将DTO属性从具有不同名称的源属性映射过来。
它与“点”表示法属性名或索引一起工作。
class PostDTO extends DataTransferObject { #[MapFrom('postTitle')] public string $title; #[MapFrom('user.name')] public string $author; } $dto = new PostDTO([ 'postTitle' => 'Hello world', 'user' => [ 'name' => 'John Doe' ] ]);
class UserDTO extends DataTransferObject { #[MapFrom(0)] public string $firstName; #[MapFrom(1)] public string $lastName; } $dto = new UserDTO(['John', 'Doe']);
有时您也希望在转换期间映射它们。一个典型的用例是从驼峰式到蛇形的情况。为此,您可以使用 #[MapTo]
属性。
class UserDTO extends DataTransferObject { #[MapFrom(0)] #[MapTo('first_name')] public string $firstName; #[MapFrom(1)] #[MapTo('last_name')] public string $lastName; } $dto = new UserDTO(['John', 'Doe']); $dto->toArray() // ['first_name' => 'John', 'last_name'=> 'Doe']; $dto->only('first_name')->toArray() // ['first_name' => 'John'];
严格的DTOs
此包的早期版本添加了 FlexibleDataTransferObject
类,允许您忽略DTO上不存在的属性。但这种行为已经改变,所有DTO现在默认都是灵活的,但您可以使用 #[Strict]
属性使它们变得严格。
class NonStrictDto extends DataTransferObject { public string $name; } // This works new NonStrictDto( name: 'name', unknown: 'unknown' );
use \Spatie\DataTransferObject\Attributes\Strict; #[Strict] class StrictDto extends DataTransferObject { public string $name; } // This throws a \Spatie\DataTransferObject\Exceptions\UnknownProperties exception new StrictDto( name: 'name', unknown: 'unknown' );
辅助函数
还提供了一些辅助函数来同时处理多个属性。
$postData->all(); $postData ->only('title', 'body') ->toArray(); $postData ->except('author') ->toArray();
请注意,all()
将简单地返回所有属性,而 toArray()
将将嵌套DTO转换为数组。
您可以将 except()
和 only()
方法链接起来
$postData ->except('title') ->except('body') ->toArray();
重要的是要注意,except()
和 only()
是不可变的,它们不会更改原始的数据传输对象。
不可变DTOs和克隆
由于PHP不支持不可变对象,因此此包不强制使用不可变对象,但您始终鼓励保持DTO不可变。为了帮助您,每个DTO都有一个接受数据以覆盖的 clone
方法
$clone = $original->clone(other: ['name' => 'a']);
请注意,$original
中的任何数据都没有改变。
DTO集合
此版本删除了 DataTransferObjectCollection
类。相反,您可以使用简单的转换器和自己的集合类。
以下是将DTO集合转换为DTO数组的一个示例
class Bar extends DataTransferObject { /** @var \Spatie\DataTransferObject\Tests\Foo[] */ #[CastWith(FooArrayCaster::class)] public array $collectionOfFoo; } class Foo extends DataTransferObject { public string $name; }
class FooArrayCaster implements Caster { public function cast(mixed $value): array { if (! is_array($value)) { throw new Exception("Can only cast arrays to Foo"); } return array_map( fn (array $data) => new Foo(...$data), $value ); } }
如果您不希望有冗余的类型提示,或者希望扩展集合功能;您可以使用任何集合实现来创建自己的集合类。在这个例子中,我们使用了Laravel的
class Bar extends DataTransferObject { #[CastWith(FooCollectionCaster::class)] public CollectionOfFoo $collectionOfFoo; } class Foo extends DataTransferObject { public string $name; }
use Illuminate\Support\Collection; class CollectionOfFoo extends Collection { // Add the correct return type here for static analyzers to know which type of array this is public function offsetGet($key): Foo { return parent::offsetGet($key); } }
class FooCollectionCaster implements Caster { public function cast(mixed $value): CollectionOfFoo { return new CollectionOfFoo(array_map( fn (array $data) => new Foo(...$data), $value )); } }
简单的DTO数组
对于简单的DTO数组或实现了PHP内置的ArrayAccess
接口的对象,建议使用ArrayCaster
,它需要一个项目类型作为参数。
class Bar extends DataTransferObject { /** @var \Spatie\DataTransferObject\Tests\Foo[] */ #[CastWith(ArrayCaster::class, itemType: Foo::class)] public array $collectionOfFoo; }
测试
composer test
更新日志
有关最近更改的更多信息,请参阅更新日志。
贡献
有关详细信息,请参阅贡献指南。
安全
如果您发现与安全相关的问题,请通过security@spatie.be发送邮件,而不是使用问题跟踪器。
明信片软件
您可以自由使用此软件包,但如果它进入您的生产环境,我们非常希望您能从家乡寄给我们一张明信片,说明您正在使用我们的哪个软件包。
我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。
我们将所有收到的明信片发布在我们的公司网站上。
外部工具
致谢
我们的Arr
类包含从Laravel的Arr
助手复制的函数。
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。