knobik / data-transfer-object
带电池的数据传输对象
Requires
- php: ^7.1
Requires (Dev)
- larapack/dd: ^1.0
- phpunit/phpunit: ^7.0
README
基于https://github.com/spatie/data-transfer-object
安装
您可以通过composer安装此软件包
composer require spatie/data-transfer-object
您是否曾经…
…与从请求、CSV文件或JSON API检索的数组数据一起工作,并想知道其中有什么内容?
以下是一个示例
public function handleRequest(array $dataFromRequest) { $dataFromRequest[/* what to do now?? */]; }
此软件包的目标是结构化“非结构化数据”,这些数据通常存储在关联数组中。通过将此数据结构化为对象,我们可以获得几个优势
- 我们可以对数据传输对象进行类型提示,而不仅仅是调用它们
array。 - 通过使我们的对象的所有属性都是可类型的,我们可以确保它们的值永远不会是我们未预期的。
- 由于属性是类型的,我们可以静态分析它们,并具有自动完成功能。
让我们看看一个JSON API调用的示例
$post = $api->get('posts', 1); [ 'title' => '…', 'body' => '…', 'author_id' => '…', ]
处理此数组很困难,因为我们始终必须参考文档才能知道其中确切的内容。此软件包允许您创建数据传输对象定义,类,这些类将以结构化的方式表示数据。
我们尽量减少语法和开销
class PostData extends DataTransferObject { /** @var string */ public $title; /** @var string */ public $body; /** @var \Author */ public $author; }
现在可以像这样构建PostData对象
$postData = new PostData([ 'title' => '…', 'body' => '…', 'author_id' => '…', ]);
现在您可以使用结构化的方式使用这些数据
$postData->title; $postData->body; $postData->author_id;
当然,您可以为PostData添加静态构造函数
class PostData extends DataTransferObject { // … public static function fromRequest(Request $request): self { return new self([ 'title' => $request->get('title'), 'body' => $request->get('body'), 'author' => Author::find($request->get('author_id')), ]); } }
通过为我们属性添加文档块,它们的值将与给定的类型进行验证;如果值不符合给定的类型,将抛出TypeError。
以下是声明类型可能的几种方式
class PostData extends DataTransferObject { /** * Built in types: * * @var string */ public $property; /** * Classes with their FQCN: * * @var \App\Models\Author */ public $property; /** * Lists of types: * * @var \App\Models\Author[] */ public $property; /** * Union types: * * @var string|int */ public $property; /** * Nullable types: * * @var string|null */ public $property; /** * Mixed types: * * @var mixed|null */ public $property; /** * No type, which allows everything */ public $property; }
当PHP 7.4引入类型属性时,您只需简单地删除文档块,并使用新的内置语法类型化属性。
处理集合
如果您正在处理DTO的集合,您可能希望对您的集合也进行自动完成和适当的类型验证。此软件包添加了一个简单的集合实现,您可以从它扩展。
use \Spatie\DataTransferObject\DataTransferObjectCollection; class PostCollection extends DataTransferObjectCollection { public function current(): PostData { return parent::current(); } }
通过重写current方法,您将在IDE中获得自动完成,并像这样使用集合。
foreach ($postCollection as $postData) { $postData-> // … your IDE will provide autocompletion. } $postCollection[0]-> // … and also here.
当然,您可以自由地实现自己的静态构造函数
class PostCollection extends DataTransferObjectCollection { public static function create(array $data): PostCollection { $collection = []; foreach ($data as $item) { $collection[] = PostData::create($item); } return new self($collection); } }
嵌套DTO的自动转换
如果您有嵌套DTO字段,传递给父DTO的数据将自动进行转换。
class PostData extends DataTransferObject { /** @var \AuthorData */ public $author; }
PostData现在可以构建如下
$postData = new PostData([ 'author' => [ 'name' => 'Foo', ], ]);
嵌套数组DTO的自动转换
类似于上述内容,嵌套数组DTO将自动进行转换。
class TagData extends DataTransferObject { /** @var string */ public $name; } class PostData extends DataTransferObject { /** @var \TagData[] */ public $tags; }
PostData将自动构建标签如下
$postData = new PostData([ 'tags' => [ ['name' => 'foo'], ['name' => 'bar'] ] ]);
注意:要使嵌套类型转换正常工作,您的Docblock定义需要是完整限定类名(例如\App\DTOs\TagData[]而不是TagData[],并在顶部使用use语句)
不可变性
如果您希望数据对象永远不会更改(在某些情况下这是一个好主意),您可以使其不可变
$postData = PostData::immutable([ 'tags' => [ ['name' => 'foo'], ['name' => 'bar'] ] ]);
尝试在构建$postData后更改其属性将导致DataTransferObjectError。
辅助函数
还提供了一些辅助函数,用于同时处理多个属性。
$postData->all(); $postData ->only('title', 'body') ->toArray(); $postData ->except('author') ->toArray();
您还可以链接这些方法
$postData ->except('title') ->except('body') ->toArray();
请注意,except 和 only 是不可变的,它们不会更改原始的数据传输对象。
异常处理
除了属性类型验证外,您还可以确信整个数据传输对象始终有效。在构建数据传输对象时,我们将验证所有必需的(非可为空的)属性是否已设置。如果没有,将抛出 Spatie\DataTransferObject\DataTransferObjectError。
同样,如果您尝试设置未定义的属性,您将得到一个 DataTransferObjectError。
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献指南。
安全
如果您发现任何安全相关的问题,请通过电子邮件freek@spatie.be联系,而不是使用问题跟踪器。
明信片软件
您可以使用这个包,但如果它进入您的生产环境,我们非常感谢您从您的家乡给我们寄一张明信片,注明您正在使用我们哪个包。
我们的地址是:Spatie,Samberstraat 69D,2060 安特卫普,比利时。
我们将在我们的公司网站上发布所有收到的明信片。
致谢
我们的 Arr 类包含从 Laravel 的 Arr 辅助函数中复制的函数。
支持我们
Spatie 是一家位于比利时的安特卫普网页设计公司。您可以在我们的网站上找到所有开源项目的概述在这里。
您的业务依赖于我们的贡献吗?联系我们在Patreon上的支持。所有承诺都将专门用于分配人力进行维护和新奇事物。
许可证
MIT 许可证(MIT)。有关更多信息,请参阅许可证文件。