Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Argonaut Dto Laravel Package

yorcreative/laravel-argonaut-dto

Lightweight, composable Laravel DTO package to transform arrays/objects/collections into typed, validated data objects. Supports deep nested casting, type-safe conversion, Laravel Validator rules, explicit attribute priority, clean toArray/toJson serialization, and immutable readonly DTOs.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package: composer require yorcreative/laravel-argonaut-dto
  2. Create your first DTO by extending ArgonautDTO or ArgonautImmutableDTO, defining typed public properties, $casts array, rules() method for validation, and optionally $nestedAssemblers for deep transformation
  3. Create an Assembler by extending ArgonautAssembler and implementing a to<DTOName>() method (e.g., toUserDTO()) to map raw input → DTO array
  4. Use it in a controller or service: Call UserDTOAssembler::assemble($rawData, UserDTO::class) or use instance methods like assembleInstance()

First practical use case: Transform a Laravel request or API response (array/object) into a strongly-typed DTO with validation before storing in database or returning in an API response. For immutable DTOs (PHP ≥8.1), extend ArgonautImmutableDTO.


Implementation Patterns

  • Static vs Instance Assemblers:

    • Use static assemblers for simple, stateless mapping (public static function to...)
    • Use instance assemblers when you need DI, e.g., to inject formatting services, repositories, or configuration (public function to...)
    • Always pass assembler instance to assemble(), fromArray(), fromCollection() methods when using non-static to...() methods.
  • Immutable DTOs (ArgonautImmutableDTO):

    • Extend ArgonautImmutableDTO for DTOs with readonly public properties (PHP ≥8.1)
    • Properties are enforced at construction; use cloneWith() for changes
    • readonly support is powered by reflection — no #[AllowDynamicProperties] needed
    • setAttributes() is deprecated; prefer cloneWith($attributes) for immutables
  • Nested DTOs & Casting:

    • Use $casts = ['nestedField' => NestedDTO::class] for single nested objects
    • Use Collection::class . ':' . ItemDTO::class for collections of DTOs
    • Use [$ItemDTO::class] for array-based DTO collections
    • New: BackedEnum casting now supported natively — use MyEnum::class, array<MyEnum::class>, or Collection::class . ':' . MyEnum::class
  • Deep Transformation with Nested Assemblers:

    • Define $nestedAssemblers = ['user' => UserDTOAssembler::class] in your DTO
    • Raw user data is auto-transformed via UserDTOAssembler::toUserDTO() before casting
  • Batch Processing:

    • Use fromArray($inputs, DTO::class) or fromCollection($collection, DTO::class) (pass assembler instance if needed)
    • Works seamlessly with Eloquent collections: MyModel::all()->transform(fn($m) => Assembler::assemble($m, DTO::class))
  • Serialization Helpers (NEW):

    • only(['field1', 'field2']) and except(['field3']) for selective serialization
    • merge(['extraKey' => $value]) to augment serialized output
    • All helpers respect $casts, readonly, and #[Ignore] attributes
  • Validation & Errors:

    • Validation runs on DTO construction via rules()
    • Errors are accessible via $dto->getValidator()->errors() if validation fails
    • Combine with Laravel’s validator() or catch ValidationException in controllers

Gotchas and Tips

  • 🔥 Assembler method naming matters: Must be to<ClassName> or from<ClassName> (case-sensitive), where <ClassName> is the basename (e.g., UserDTOtoUserDTO, not toUser)

  • 🐞 DI doesn’t work in static methods: If your toUserDTO() method needs services, make it non-static and ensure you pass an assembler instance to assemble(), fromArray, etc.

  • 🧩 Cast order of operations (unchanged, now reinforced by trait refactor):

    1. Raw input is processed
    2. If $nestedAssemblers exists for the key, assembler runs
    3. Then $casts is applied (including BackedEnum)
    4. Finally, __construct assigns and casts (including readonly enforcement)
  • ⚠️ Immutable DTOs require PHP ≥8.1:

    • readonly fields throw type errors on reassignment — always use ?DTO for nullable fields
    • cloneWith() creates a shallow copy with new values — useful in services (e.g., state transitions)
  • 📦 Serialization improvements:

    • toArray()/toJson() now respect only(), except(), merge() helpers
    • #[Ignore] still works for excluding fields, but prefer only()/except() for clean explicitness
    • BackedEnum values serialize as their scalar backing value ('active' for StatusEnum::ACTIVE)
  • 🧪 Testing tip: Mock or resolve() assemblers — e.g., make(UserAssembler::class) in tests. For immutables, verify cloneWith() side effects.

  • 🔄 Deep cast fallbacks: If a nested DTO field is null but not nullable (e.g., UserDTO instead of ?UserDTO), PHP throws TypeError. Always type-hint nullable fields with ?.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport