tuxonice / transfer-objects
从JSON定义构建数据传输对象
v1.1.2
2024-04-05 17:49 UTC
Requires
- php: ^8.0
- ext-json: *
- opis/json-schema: ^2.3
- twig/twig: ^3.5
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.1
- squizlabs/php_codesniffer: ^3.7
- symfony/var-dumper: ^6.2
README
在软件开发的不断演变的领域中,高效和结构化的数据通信至关重要。DTO包旨在简化并增强数据在应用程序不同层之间的传输方式,促进清晰性、可维护性和健壮性。
无论您是在构建RESTful API、微服务架构还是传统Web应用程序,数据传输对象包都赋予您优雅和精确地管理数据流的权力。通过我们直观且面向开发者的DTO解决方案,提升代码质量并简化数据处理流程。
安装
您可以通过composer安装此包
composer require tuxonice/transfer-objects
设置
此包的目标是从JSON定义尽可能容易地创建数据传输对象。
- 在您的项目中创建一个文件夹来保存定义文件。
mkdir "src/dto-definitions"
- 创建一个文件夹来保存生成的数据传输对象
mkdir "src/DataTransferObjects"
- 创建一个命令来生成DTO。如果您使用symfony控制台,可能是以下内容:
namespace Acme\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Tlab\TransferObjects\DataTransferBuilder; class GenerateTransferCommand extends Command { protected static $defaultName = 'transfer:generate'; protected function configure(): void { $this ->setDescription('Generate transfer objects') ->setHelp('Generate transfer objects'); } protected function execute(InputInterface $input, OutputInterface $output): int { $dataTransferBuilder = new DataTransferBuilder( dirname(__DIR__) . '/dto-definitions/', dirname(__DIR__) . '/DataTransferObjects/', 'Acme\\DataTransferObjects', ); $dataTransferBuilder->build(); return Command::SUCCESS; } }
- Laravel项目
php artisan make:command GenerateTransfer
namespace App\Console\Commands; use Illuminate\Console\Command; use Tlab\TransferObjects\DataTransferBuilder; class GenerateTransfer extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'transfer:generate'; /** * The console command description. * * @var string */ protected $description = 'Generate data transfer objects'; /** * Execute the console command. */ public function handle(): void { $dataTransferBuilder = new DataTransferBuilder( dirname(__DIR__) . '/dto-definitions/', dirname(__DIR__) . '/DataTransferObjects/', 'Acme\\DataTransferObjects', ); $dataTransferBuilder->build(); } }
- 通过定义文件定义DTO
src/dto-definitions/customer.json
{ "transfers": [ { "name": "Customer", "properties": [ { "name": "firstName", "type": "string" }, { "name": "lastName", "type": "string", "nullable": true }, { "name": "email", "type": "string", "nullable": false }, { "name": "birthDate", "type": "DateTime", "namespace": "DateTime" }, { "name": "isActive", "type": "bool" } ] } ] }
此定义将生成以下传输类
namespace Acme\DataTransferObjects; use DateTime; use Tlab\TransferObjects\AbstractTransfer; /** * !!! THIS TRANSFER CLASS FILE IS AUTO-GENERATED, CHANGES WILL BREAK YOUR PROJECT * !!! DO NOT CHANGE ANYTHING IN THIS FILE */ class CustomerTransfer extends AbstractTransfer { /** * @var string */ private string $firstName; /** * @var string|null */ private ?string $lastName; /** * @var string */ private string $email; /** * @var DateTime */ private DateTime $birthDate; /** * @var bool */ private bool $isActive; /** * @return string */ public function getFirstName(): string { return $this->firstName; } /** * @param string $firstName * * @return $this */ public function setFirstName(string $firstName): self { $this->firstName = $firstName; return $this; } /** * @return string|null */ public function getLastName(): ?string { return $this->lastName; } /** * @param string|null $lastName * * @return $this */ public function setLastName(?string $lastName): self { $this->lastName = $lastName; return $this; } /** * @return string */ public function getEmail(): string { return $this->email; } /** * @param string $email * * @return $this */ public function setEmail(string $email): self { $this->email = $email; return $this; } /** * @return DateTime */ public function getBirthDate(): DateTime { return $this->birthDate; } /** * @param DateTime $birthDate * * @return $this */ public function setBirthDate(DateTime $birthDate): self { $this->birthDate = $birthDate; return $this; } /** * @return bool */ public function getIsActive(): bool { return $this->isActive; } /** * @param bool $isActive * * @return $this */ public function setIsActive(bool $isActive): self { $this->isActive = $isActive; return $this; } }
用法
创建和设置数据
$customerTransfer = new CustomerTransfer(); $customerTransfer ->setFirstName('John') ->setLastName('Smith') ->setEmail('user@example.com') ->setBirthDate(new DateTime('2000-01-01')) ->setIsActive(true);
获取数据
$firstName = $customerTransfer->getFirstName(); // John $lastName = $customerTransfer->getLastName(); // Smith
从数组创建
在从数组创建时,可以使用两者 camelCase 或 snake_case 作为数组键
$data = [ 'first_name' => 'John', 'last_name' => 'Smith', 'email' => 'user@example.com', 'birth_date' => new DateTime('2000-01-01'), 'is_active' => true), ]; $customerTransfer = CustomerTransfer::fromArray($data); $data = [ 'streetName' => 'test street name', 'city' => 'test-city', 'zipCode' => '1999', 'isDefaultBillingAddress' => true, 'isDefaultShippingAddress' => false, ]; $addressTransfer = AddressTransfer::fromArray($data);
导出到数组
$customerTransfer = new CustomerTransfer(); $customerTransfer ->setFirstName('John') ->setLastName('Smith') ->setEmail('user@example.com') ->setBirthDate(new DateTime('2000-01-01')) ->setIsActive(true); $data = $customerTransfer->toArray();
将返回
[ 'firstName' => 'John', 'lastName' => 'Smith', 'email' => 'user@example.com', 'birthDate' => new DateTime('2000-01-01'), 'isActive' => true, ]
toArray()
方法有两个参数
public function toArray(bool $isRecursive = false, bool $snakeCaseKeys = false): array
isRecursive
当为true时,也会将子传输对象导出到数组
$customerTransfer = new CustomerTransfer(); $customerTransfer ->setEmail('user@example.com') ->setBirthDate(new DateTime('2000-01-01')) ->setFirstName('John') ->setLastName('Smith') ->setIsActive(true); $orderItemTransfer1 = new OrderItemTransfer(); $orderItemTransfer1 ->setName('Chips') ->setPrice(5.99) ->setQuantity(1) ->setId(1); $orderItemTransfer2 = new OrderItemTransfer(); $orderItemTransfer2 ->setName('Juice') ->setPrice(3.45) ->setQuantity(2) ->setId(2); $orderTransfer = new OrderTransfer(); $orderTransfer ->setId(1) ->setCustomer($customerTransfer) ->setTotal(10.00) ->setOrderItems([ $orderItemTransfer1, $orderItemTransfer2 ]) ->setCreatedAt(new DateTime('2023-10-01')); $data = $orderTransfer->toArray(true);
将返回
[ 'id' => 1, 'customer' => [ 'firstName' => 'John', 'lastName' => 'Smith', 'email' => 'user@example.com', 'birthDate' => new DateTime('2000-01-01'), 'isActive' => true, ], 'total' => 10.0, 'orderItems' => [ [ 'id' => 1, 'name' => 'Chips', 'price' => 5.99, 'quantity' => 1, ], [ 'id' => 2, 'name' => 'Juice', 'price' => 3.45, 'quantity' => 2, ], ], 'createdAt' => new DateTime('2023-10-01'), ]
snakeCaseKeys
当为true时,也会导出具有 snake_case 键的数组(默认为 camelCase)
$customerTransfer = new CustomerTransfer(); $customerTransfer ->setFirstName('John') ->setLastName('Smith') ->setEmail('user@example.com') ->setBirthDate(new DateTime('2000-01-01')) ->setIsActive(true); $data = $customerTransfer->toArray(false, true);
将返回
[ 'first_name' => 'John', 'last_name' => 'Smith', 'email' => 'user@example.com', 'birth_date' => new DateTime('2000-01-01'), 'is_active' => true, ]
创建定义文件
您可以为每个JSON文件定义一个或多个传输对象定义。首先创建一个包含您定义的JSON对象
{
"transfers": [
]
}
然后在transfers
数组中定义您的传输
{ "name": "Customer", "properties": [ { "name": "firstName", "type": "string" }, { "name": "lastName", "type": "string" }, { "name": "isActive", "type": "bool" } ] }
可用字段
- 类
- 类属性
属性定义示例
- 整数
{ "name": "id", "type": "int" }
- 可为空的字符串
{ "name": "firstName", "type": "string", "nullable": true }
- 作为属性的另一个传输对象
{ "name": "customer", "type": "CustomerTransfer" }
- 日期时间属性
{ "name": "createdAt", "type": "DateTime", "namespace": "DateTime" }
- 字符串数组
{ "name": "tags", "type": "string[]", "singular": "tag" }
- 传输对象数组
{ "name": "categories", "type": "CategoryTransfer[]", "singular": "category" }
- Symfony响应
{ "name": "response", "type": "Response", "namespace": "\\Symfony\\Component\\HttpFoundation\\Response" }
许可证
MIT许可证(MIT)。请参阅许可证文件获取更多信息。