ccharz/laravel-dto-lite

简单的 Laravel 数据传输对象

v3.2.0 2024-09-20 08:47 UTC

This package is auto-updated.

Last update: 2024-09-20 08:52:41 UTC


README

这是数据传输对象(DTO)概念的基本实现。其想法是描述数据的一个简单基本的 PHP 类文件中的输入和输出。它旨在替换 FormRequests 和 Resources,也可以用于自动生成 TypeScript 定义。

此包与 Spatie 的 Laravel Data 包类似。主要区别在于它不包含反射类魔法,仅提供基本功能。

安装

composer require ccharz/laravel-dto-lite

使用方法

示例 DTO

enum ContactType : string {
    case PERSON = 'person';
    case COMPANY = 'company';
}

class ContactData extends DataTransferObject {
    public function __construct(
        public readonly string $name,
        public readonly string $email,
        public readonly ContactType $type,
    ) {}
}

类型转换

属性的类型转换可以定义为与 eloquent 类型转换类似。也可以定义数组到类型的转换。

enum ContactType : string {
    case PERSON = 'person';
    case COMPANY = 'company';
}

class AddressData extends DataTransferObject
{
    public function __construct(
        public readonly ?string $country = null,
        public readonly ?string $zip = null,
        public readonly ?string $location = null,
        public readonly ?string $street = null,
        public readonly ?string $streetnumber = null,
        public readonly ?string $stair = null,
        public readonly ?string $top = null,
    ) {
    }
}

class ContactData extends DataTransferObject {
    public function __construct(
        /** @var AddressData[] $addresses */
        public readonly array $addresses,
        public readonly DateTime $birthday,
        public readonly ContactType $type,
    ) {}

    public static function casts(): array
    {
        return [
            'addresses' => AddressData::class . '[]',
            'birthday' => 'datetime',
            'type' =>  ContactType::class,
        ];
    }
}

验证

如果存在规则方法,则在手动或通过自动依赖注入从请求创建 DTO 时将自动执行验证。

use Illuminate\Http\Request;

public static function rules(?Request $request = null): ?array
{
    return ['prename' => 'min:2'];
}

您还可以将类型转换的规则注入到您的规则中

use Illuminate\Http\Request;

public static function rules(?Request $request = null): ?array
{
    return [
        ...parent::castRules(),
    ];
}

自动注入

借助 Laravel 的依赖注入,DTO 可以在控制器方法函数中使用,并自动用请求中的 已验证 输入数据填充。

public function store(ContactData $contactData): RedirectResponse
{
    Contact::create([
        'name' => $contactData->name,
        'email' => $contactData->email,
    ]);

    return redirect()->back();
}

Eloquent 可转换

数据传输对象可以用作 Eloquent 模型的类型转换

class Contact extends Model
{
    protected $casts = [
        'address' => AddressData::class,
    ];
}

如果列是可空的,则必须附加 "nullable" 类型参数

class Contact extends Model
{
    protected $casts = [
        'address' => AddressData::class . ':nullable',
    ];
}

响应

如果从控制器返回,数据传输对象将自动转换为响应

class ContactController extends Controller {
    public function show(Contact $contact): ContactData
    {
        return ContactData::make($contact);
    }
}

您还可以返回数据传输对象 资源集合

class ContactController extends Controller {
    public function index()
    {
        return ContactData::resourceCollection(Contact::paginate());
    }
}

映射到 DTO 数组

数组可以自动映射到 DTO 数组

$addresses = [
    [
        'country' => 'AT',
        'zip' => '8010',
    ],
    [
        'country' => 'AT',
        'zip' => '8010',
    ]
];

AddressData::mapToDtoArray($addresses);

Typescript 定义

您可以使用 https://github.com/spatie/laravel-typescript-transformer 自动为您的数据传输对象和枚举生成 TypeScript 定义。

namespace App\Data;

use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript]
class AddressData extends DataTransferObject
{
    public function __construct(
        public readonly ?string $country = null,
        public readonly ?string $zip = null,
        public readonly ?string $location = null,
        public readonly ?string $street = null,
        public readonly ?string $streetnumber = null,
        public readonly ?string $stair = null,
        public readonly ?string $top = null,
    ) {
    }
}

生成以下 TypeScript 定义

declare namespace App.Data {
    export type AddressData = {
        country: string | null;
        zip: string | null;
        location: string | null;
        street: string | null;
        streetnumber: string | null;
        stair: string | null;
        top: string | null;
    };
}

Artisan 命令

要创建新的数据传输对象,请使用 make:dto Artisan 命令。

php artisan make:dto Address