tuxonice/transfer-objects

从JSON定义构建数据传输对象

v1.1.2 2024-04-05 17:49 UTC

This package is auto-updated.

Last update: 2024-09-05 19:27:17 UTC


README

Build Status Total Downloads Latest Stable Version License

在软件开发的不断演变的领域中,高效和结构化的数据通信至关重要。DTO包旨在简化并增强数据在应用程序不同层之间的传输方式,促进清晰性、可维护性和健壮性。

无论您是在构建RESTful API、微服务架构还是传统Web应用程序,数据传输对象包都赋予您优雅和精确地管理数据流的权力。通过我们直观且面向开发者的DTO解决方案,提升代码质量并简化数据处理流程。

安装

您可以通过composer安装此包

composer require tuxonice/transfer-objects

设置

此包的目标是从JSON定义尽可能容易地创建数据传输对象。

  1. 在您的项目中创建一个文件夹来保存定义文件。
mkdir "src/dto-definitions"
  1. 创建一个文件夹来保存生成的数据传输对象
mkdir "src/DataTransferObjects"
  1. 创建一个命令来生成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;
    }
}
  1. 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();
    }
}
  1. 通过定义文件定义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

从数组创建

在从数组创建时,可以使用两者 camelCasesnake_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)。请参阅许可证文件获取更多信息。