警告我们决定停止维护此软件包。
考虑迁移到 spatie/laravel-data 或 cuyz/valinor。
请随意分叉我们的代码并根据您的需求进行调整。
您可以通过 Composer 安装该软件包:
作曲家需要空间/数据传输对象
注意:此软件包的 v3 仅支持php:^8.0
。如果您正在寻找旧版本,请查看 v2。
我们投入了大量资源来创建一流的开源包。您可以通过购买我们的一款付费产品来支持我们。
我们非常感谢您从家乡寄给我们一张明信片,并注明您正在使用我们的哪种套餐。您可以在我们的联系页面上找到我们的地址。我们在虚拟明信片墙上发布所有收到的明信片。
该包的目标是尽可能轻松地从(序列化)数据数组构造对象。 DTO 如下所示:
使用 SpatieDataTransferObjectAttributesMapFrom;使用 SpatieDataTransferObjectDataTransferObject;类 MyDTO 扩展 DataTransferObject {公共OtherDTO $otherDTO; 公共OtherDTOCollection$集合; #[CastWith(ComplexObjectCaster::class)]public ComplexObject $complexObject; 公共 ComplexObjectWithCast $complexObjectWithCast; #[NumberBetween(1, 100)]public int $a; #[MapFrom('address.city')]public string $city; }
您可以像这样构造这个 DTO:
$dto = 新的 MyDTO( 答:5, 收藏: [ ['id' => 1], ['id' => 2], ['id' => 3], ], 复杂对象:['名称'=>'测试', ], ComplexObjectWithCast: ['名称' => '测试', ], otherDTO: ['id' => 5], );
让我们一一讨论所有的可能性。
可以使用命名参数来构建 DTO。也可以仍然使用旧的数组表示法。此示例与上面的示例等效。
$dto = new MyDTO(['a' => 5,'collection' => [ ['id' => 1], ['id' => 2], ['id' => 3], ],'complexObject' => ['名称' => '测试', ],'complexObjectWithCast' => ['名称' => '测试', ],'otherDTO' => ['id' => 5], ]);
如果 DTO 具有属于另一个 DTO 或 DTO 集合的属性,则该包将自动将数据数组转换为这些 DTO:
$dto = 新的 MyDTO( collection: [ // 这将成为 OtherDTOCollection['id' => 1] 类的对象, ['id' => 2], // 每个项目都是 OtherDTO['id' => 3], ], otherDTO: ['id' => 5], // 该数据将被转换为 OtherDTO);
您可以构建自己的caster类,它将接受给定的任何输入,并将该输入转换为所需的结果。
看一下ComplexObject
:
复杂对象类 {公共字符串$名称; }
及其施法者ComplexObjectCaster
:
使用 SpatieDataTransferObjectCaster;类 ComplexObjectCaster 实现 Caster {/** * @param array|mixed $value * * @return mix */public function cast(mixed $value): ComplexObject{return new ComplexObject( 名称:$值['名称'] ); } }
您还可以在目标类本身上定义该施法器,而不是指定每个属性应使用哪个施法器:
MyDTO 类扩展了 DataTransferObject {公共 ComplexObjectWithCast $complexObjectWithCast; }
#[CastWith(ComplexObjectWithCastCaster::class)]类 ComplexObjectWithCast {公共字符串$名称; }
可以在 DTO 类本身上定义默认脚轮。每当在 DTO 类中遇到给定类型的属性时,就会使用这些caster。
#[ DefaultCast(DateTimeImmutable::class, DateTimeImmutableCaster::class), DefaultCast(MyEnum::class, EnumCaster::class), ] 抽象类 BaseDataTransferObject 扩展 DataTransferObject {public MyEnum $status; // 将使用 EnumCasterpublic DateTimeImmutable $date; // 将使用 DateTimeImmutableCaster}
任何caster都可以传递自定义参数,内置的ArrayCaster
实现是如何使用它的一个很好的例子。
将输入传递给施法者时使用命名参数将有助于使您的代码更加清晰,但这不是必需的。
例如:
/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]公共数组 $collectionWithNamedArguments; /** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, Foo::class)]公共数组 $collectionWithoutNamedArguments;
请注意,传递给强制转换构造函数的第一个参数始终是具有被强制转换值类型的数组。所有其他参数都将作为CastWith
属性中的额外参数传递。
该包不提供任何特定的验证功能,但它确实为您提供了一种构建自己的验证属性的方法。例如, NumberBetween
是用户实现的验证属性:
MyDTO 类扩展了 DataTransferObject { #[NumberBetween(1, 100)]public int $a; }
它的工作原理如下:
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]类 NumberBetween 实现 Validator {公共函数 __construct(私有 int $min,私有 int $max) { }public function validate(mixed $value): ValidationResult{if ($value < $this->min) {return ValidationResult::invalid("值应该大于或等于 {$this->min}"); }if ($value > $this->max) {return ValidationResult::invalid("值应小于或等于 {$this->max}"); }返回验证结果::valid(); } }
您可以使用#[MapFrom]
属性从具有不同名称的源属性映射 DTO 属性。
它与“点”表示法属性名称或索引一起使用。
PostDTO 类扩展了 DataTransferObject { #[MapFrom('postTitle')]public string $title; #[MapFrom('user.name')]public string $author; }$dto = new PostDTO(['postTitle' => 'Hello world','user' => ['name' => 'John Doe'] ]);
UserDTO 类扩展 DataTransferObject { #[MapFrom(0)]公共字符串$firstName; #[MapFrom(1)]公共字符串$lastName; }$dto = new UserDTO(['John', 'Doe']);
有时您还想在转换为数组期间将它们映射。一个典型的用例是从骆驼案例到蛇案例的转换。为此,您可以使用#[MapTo]
属性。
UserDTO 类扩展 DataTransferObject { #[地图来源(0)] #[MapTo('first_name')]public string $firstName; #[地图来源(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'];
此包的先前版本添加了FlexibleDataTransferObject
类,该类允许您忽略DTO 上不存在的属性。此行为已更改,默认情况下所有 DTO 现在都是灵活的,但您可以使用#[Strict]
属性使其严格:
NonStrictDto 类扩展了 DataTransferObject {公共字符串$名称; }// 这有效 new NonStrictDto( 名称:'名称', 未知:“未知”);
使用 SpatieDataTransferObjectAttributesStrict; #[Strict]类 StrictDto 扩展 DataTransferObject {公共字符串$名称; }// 这会抛出 SpatieDataTransferObjectExceptionsUnknownProperties 异常new StrictDto( 名称:'名称', 未知:“未知”);
还提供了一些辅助函数,用于同时处理多个属性。
$postData->all();$postData->only('标题', '正文') ->toArray(); $postData-> except('作者') ->toArray();
请注意, all()
将简单地返回所有属性,而toArray()
也会将嵌套的 DTO 转换为数组。
您可以链接except()
和only()
方法:
$postData->除了('标题') ->除了('身体') ->toArray();
需要注意的是except()
和only()
是不可变的,它们不会改变原始数据传输对象。
该包不会强制使用不可变对象,因为 PHP 不支持它们,但始终鼓励您保持 DTO 不可变。为了帮助您,每个 DTO 上都有一个clone
方法,它接受要覆盖的数据:
$clone = $original->clone(other: ['name' => 'a']);
请注意, $original
中的数据没有更改。
此版本删除了DataTransferObjectCollection
类。相反,您可以使用简单的脚轮和您自己的集合类。
以下是将 DTO 集合转换为 DTO 数组的示例:
Bar 类扩展了 DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(FooArrayCaster::class)]公共数组 $collectionOfFoo; }类 Foo 扩展了 DataTransferObject {公共字符串$名称; }
类 FooArrayCaster 实现 Caster {public function cast(mixed $value): array{if (! is_array($value)) { throw new Exception("只能将数组转换为 Foo"); }return array_map(fn (array $data) => new Foo(...$data),$value); } }
如果你不想要多余的类型提示,或者想要扩展的集合功能;您可以使用任何集合实现来创建自己的集合类。在这个例子中,我们使用 Laravel 的:
Bar 类扩展了 DataTransferObject { #[CastWith(FooCollectionCaster::class)]public CollectionOfFoo $collectionOfFoo; }类 Foo 扩展了 DataTransferObject {公共字符串$名称; }
使用 IlluminateSupportCollection;class CollectionOfFoo 扩展 Collection {// 在这里添加正确的返回类型,以便静态分析器知道这是哪种类型的数组 public function offsetGet($key): Foo{returnparent::offsetGet($key); } }
FooCollectionCaster 类实现 Caster {公共函数cast(混合$value): CollectionOfFoo{return new CollectionOfFoo(array_map(fn (array $data) => new Foo(...$data),$value)); } }
对于简单的 DTO 数组或实现 PHP 内置ArrayAccess
的对象,请考虑使用需要提供项目类型的ArrayCaster
:
Bar 类扩展了 DataTransferObject {/** @var SpatieDataTransferObjectTestsFoo[] */#[CastWith(ArrayCaster::class, itemType: Foo::class)]公共数组 $collectionOfFoo; }
作曲家测试
请参阅变更日志以了解有关最近更改内容的更多信息。
详细信息请参阅贡献。
如果您发现有关安全的错误,请发送邮件至 [email protected],而不是使用问题跟踪器。
您可以自由使用这个软件包,但如果它进入您的生产环境,我们非常感谢您从您的家乡给我们寄一张明信片,注明您正在使用我们的哪个软件包。
我们的地址是:Spatie, Kruikstraat 22, 2018 安特卫普, 比利时。
我们在公司网站上发布所有收到的明信片。
json2dto:一个用于将 JSON 对象转换为 DTO 类的 GUI(具有嵌套支持)。还提供了供本地使用的 CLI 工具。
数据传输对象工厂:根据名称和类型使用属性的正确内容智能生成 DTO 实例。
布伦特·罗斯
所有贡献者
我们的Arr
类包含从 Laravels Arr
助手复制的函数。
麻省理工学院许可证 (MIT)。请参阅许可证文件以获取更多信息。