ccharz / laravel-dto-lite
简单的 Laravel 数据传输对象
v3.2.0
2024-09-20 08:47 UTC
Requires
- php: ^8.2
- laravel/framework: ^10.0|^11.0
Requires (Dev)
- larastan/larastan: ^2.0
- laravel/pint: ^1.14
- orchestra/testbench: ^8.17|^9.0
- rector/rector: ^1.2
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