Data Transfer Objects using Spatie Laravel Data. Type-safe data handling with validation and transformation.
composer require spatie/laravel-data
// ❌ Arrays - Sin tipos, sin autocomplete, sin validación
public function create(array $data) {}
// ✅ DTO - Type-safe, autocomplete, validado
public function create(UserData $data) {}
<?php
namespace App\DataTransferObjects;
use Spatie\LaravelData\Data;
class {{Model}}Data extends Data
{
public function __construct(
public string $name,
public string $email,
public ?string $phone = null,
) {}
public static function fromRequest(Store{{Model}}Request $request): self
{
return new self(
name: $request->validated('name'),
email: $request->validated('email'),
phone: $request->validated('phone'),
);
}
public function toArray(): array
{
return [
'name' => $this->name,
'email' => strtolower($this->email),
'phone' => $this->phone,
];
}
}
use Spatie\LaravelData\Attributes\Validation\{Email, Min, Required};
class UserData extends Data
{
public function __construct(
#[Required, Min(3)]
public string $name,
#[Required, Email]
public string $email,
) {}
}
class AddressData extends Data
{
public function __construct(
public string $street,
public string $city,
) {}
}
class UserData extends Data
{
public function __construct(
public string $name,
public AddressData $address,
) {}
}
// Controller
public function store(StoreUserRequest $request, CreateUser $action): UserResource
{
return UserResource::make(
$action->execute(UserData::fromRequest($request))
);
}
// Action
class CreateUser
{
public function execute(UserData $data): User
{
return User::create($data->toArray());
}
}
it('creates DTO from request', function () {
$request = StoreUserRequest::create('/', 'POST', [
'name' => 'John',
'email' => '[email protected]',
]);
$data = UserData::fromRequest($request);
expect($data->name)->toBe('John')
->and($data->email)->toBe('[email protected]');
});
SIEMPRE usa DTOs en lugar de arrays para: