مقاله

ساخت DTO با readonly class، Spatie Laravel Data و map از Request — جایگزین array پراکنده بین لایه‌ها.

DTO در Laravel — Data Transfer Object برای داده ساخت‌یافته

DTO در Laravel — Data Transfer Object برای داده ساخت‌یافته

$request->validated() یک array است — کار می‌کند تا وقتی کلید اشتباه تایپ شود، IDE autocomplete ندهد و refactor بشکند. DTO (Data Transfer Object) شیء immutable با type مشخص است که بین Request، Action، Service و گاه API جریان می‌یابد.

DTO ساده با readonly PHP 8.2+

readonly class CreatePostData
{
    public function __construct(
        public string $title,
        public string $slug,
        public string $content,
        public ?string $excerpt = null,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            title: $data['title'],
            slug: $data['slug'],
            content: $data['content'],
            excerpt: $data['excerpt'] ?? null,
        );
    }
}

از Form Request

class StorePostRequest extends FormRequest
{
    public function rules(): array { /* ... */ }

    public function toDto(): CreatePostData
    {
        return CreatePostData::fromArray($this->validated());
    }
}

Form Request پیشرفته.

در Action

public function handle(CreatePostData $data, User $author): Post
{
    return $this->posts->create([
        'title' => $data->title,
        'slug' => $data->slug,
        'content' => $data->content,
        'excerpt' => $data->excerpt,
        'user_id' => $author->id,
    ]);
}

Action Class signature واضح — نه array $data.

Spatie Laravel Data

پکیج محبوب: validation، cast، از Request/Model:

use Spatie\LaravelData\Data;

class CreatePostData extends Data
{
    public function __construct(
        public string $title,
        public string $slug,
        public string $content,
    ) {}
}

// CreatePostData::from($request);

برای پروژه بزرگ با DTO زیاد ارزش دارد؛ CRUD کوچک readonly class کافی.

DTO vs Model

Model (Eloquent)DTO
persist + relation + DBفقط حمل داده بین لایه
mutableترجیحاً immutable
Active Recordinput/output contract

DTO vs Value Object

DTO bag of fields برای transfer؛ Value Object domain concept با invariant (مثلاً Email). گاه VO داخل DTO.

API Resource و DTO

DTO از request → Action → return Model → Resource برای JSON. DTO جایگزین Resource نیست.

اشتباهات

  • DTO با ۵۰ فیلد god object
  • logic business داخل DTO
  • DTO برای هر خط CRUD بدون benefit

جمع‌بندی

DTO وقتی لایه‌ها جدا و type safety مهم است. Clean: Clean Code. Service: Service vs Action.

architecture با DTO