PHPackages                             yorcreative/laravel-argonaut-dto - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. yorcreative/laravel-argonaut-dto

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

yorcreative/laravel-argonaut-dto
================================

Argonaut is a lightweight Data Transfer Object (DTO) package for Laravel that supports nested casting, recursive serialization, and validation out of the box. Ideal for service layers, APIs, and clean architecture workflows.

v1.4.0(4mo ago)1053.4k↓21.4%51MITPHPPHP ^8.2|^8.3|^8.4|^8.5CI failing

Since Apr 20Pushed 4mo agoCompare

[ Source](https://github.com/YorCreative/Laravel-Argonaut-DTO)[ Packagist](https://packagist.org/packages/yorcreative/laravel-argonaut-dto)[ GitHub Sponsors](https://github.com/yorcreative)[ RSS](/packages/yorcreative-laravel-argonaut-dto/feed)WikiDiscussions main Synced 3d ago

READMEChangelog (5)Dependencies (10)Versions (10)Used By (1)

 [ ![Logo](content/Laravel-Argonaut-DTO.png) ](https://github.com/YorCreative)

### Laravel Argonaut DTO

[](#laravel-argonaut-dto)

[![GitHub license](https://camo.githubusercontent.com/51223c0935864a47c2a34ef3f61000d31d03f82886a6f5e81a14b7021a8589da/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f596f7243726561746976652f4c61726176656c2d4172676f6e6175742d44544f)](https://github.com/YorCreative/Laravel-Argonaut-DTO/blob/main/LICENSE.md)[![GitHub stars](https://camo.githubusercontent.com/eee7ebe7f308a1c6cf635e740238ae5edb735d7451da6df4124ac0866e4e1e28/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f596f7243726561746976652f4c61726176656c2d4172676f6e6175742d44544f3f6c6162656c3d5265706f2532305374617273)](https://github.com/YorCreative/Laravel-Argonaut-DTO/stargazers)[![GitHub Org's stars](https://camo.githubusercontent.com/c3aef82ca684110e373af0e3676f82fd43ae79ae081691bd87c7e713f993435e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f596f7243726561746976653f7374796c653d736f6369616c266c6162656c3d596f7243726561746976652532305374617273266c696e6b3d68747470732533412532462532466769746875622e636f6d253246596f724372656174697665)](https://camo.githubusercontent.com/c3aef82ca684110e373af0e3676f82fd43ae79ae081691bd87c7e713f993435e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f596f7243726561746976653f7374796c653d736f6369616c266c6162656c3d596f7243726561746976652532305374617273266c696e6b3d68747470732533412532462532466769746875622e636f6d253246596f724372656174697665)[![GitHub issues](https://camo.githubusercontent.com/31b879d33847ac2db2ff20378ae405f4568cc3ba421bdf5762839326e21d68b2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f596f7243726561746976652f4c61726176656c2d4172676f6e6175742d44544f)](https://github.com/YorCreative/Laravel-Argonaut-DTO/issues)[![GitHub forks](https://camo.githubusercontent.com/4bb3440508cfff30a2611cbfac8b9d0fad179c9ae5b582c49fe471d3461bd4e9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f596f7243726561746976652f4c61726176656c2d4172676f6e6175742d44544f)](https://github.com/YorCreative/Laravel-Argonaut-DTO/network)[![PHPUnit](https://github.com/YorCreative/Laravel-Argonaut-DTO/actions/workflows/phpunit-tests.yml/badge.svg)](https://github.com/YorCreative/Laravel-Argonaut-DTO/actions/workflows/phpunit-tests.yml)

Laravel Argonaut DTO is a lightweight, highly composable package for transforming arrays, objects, or collections into structured DTOs (Data Transfer Objects), with built-in support for:

- 🧱 Deep nested transformation and casting
- 🔁 Type-safe data conversion
- ✅ Validation using Laravel's validator
- 🧠 Explicit attribute prioritization
- 📦 Clean serialization (`toArray`, `toJson`)
- 🔒 Immutable DTOs with readonly properties
- ♻️ Consistent data shape enforcement across boundaries

---

📦 Installation
--------------

[](#-installation)

Install via Composer:

```
composer require yorcreative/laravel-argonaut-dto
```

---

🚀 Quick Start
-------------

[](#-quick-start)

### 1. Define a DTO

[](#1-define-a-dto)

DTOs extend `ArgonautDTO`, and define your expected structure via public properties, casting rules, and validation.

```
class UserDTO extends ArgonautDTO
{
    public string $username;
    public string $email;

    protected array $casts = [
        'username' => 'string',
        'email' => 'string',
    ];

    public function rules(): array
    {
        return [
            'username' => ['required', 'string'],
            'email' => ['required', 'email'],
        ];
    }
}
```

This defines a strongly typed DTO with both validation rules and simple type casting.

---

### 2. Create an Assembler

[](#2-create-an-assembler)

Assemblers are responsible for mapping raw inputs (arrays or objects) into your DTOs.

```
// static usage example
class UserDTOAssembler extends ArgonautAssembler
{
    public static function toUserDTO(object $input): UserDTO
    {
        return new UserDTO([
            'username' => $input->display_name,
            'email' => $input->email,
        ]);
    }
}

// instance usage example
class UserDTOAssembler extends ArgonautAssembler
{
    public function __construct(protected UserFormattingService $formattingService)
    {
        //
    }

    public function toUserDTO(object $input): UserDTO
    {
        return new UserDTO([
            'username' => $this->formattingService->userName($input->display_name),
            'email' => $this->formattingService->email($input->email),
        ]);
    }
}
```

> Assembler method names must follow the format `to` or `from`, and are resolved automatically using `class_basename`.

---

### 3. Assemble a DTO

[](#3-assemble-a-dto)

Use the assembler to transform raw data into structured, casted DTO instances.

```
// static usage example
$dto = UserDTOAssembler::assemble([
    'display_name' => 'jdoe',
    'email' => 'jdoe@example.com',
], UserDTO::class);

// instance usage example
$dto = $userDTOAssemblerInstance->assembleInstance([
    'display_name' => 'jdoe',
    'email' => 'jdoe@example.com',
], UserDTO::class);
```

You can also batch transform arrays or collections:

```
// static usage
UserDTOAssembler::fromArray($userArray, UserDTO::class);
UserDTOAssembler::fromCollection($userCollection, UserDTO::class);

// instance usage
UserDTOAssembler::fromArray($userArray, UserDTO::class, $userDTOAssemblerInstance);
UserDTOAssembler::fromCollection($userCollection, UserDTO::class, $userDTOAssemblerInstance);

// or using the assembler instance's static methods
$userDTOAssemblerInstance::fromArray($userArray, UserDTO::class, $userDTOAssemblerInstance);
$userDTOAssemblerInstance::fromCollection($userCollection, UserDTO::class, $userDTOAssemblerInstance);
```

---

🧪 Real-World Static Usage Example: Product + Features + Reviews
---------------------------------------------------------------

[](#-real-world-static-usage-example-product--features--reviews)

This example demonstrates nested relationships and complex type casting in action.

### ProductDTO with nested casting:

[](#productdto-with-nested-casting)

```
class ProductDTO extends ArgonautDTO
{
    public string $title;
    public array $features;
    public Collection $reviews;
    public ?UserDTO $user = null;

    protected array $casts = [
        'features' => [ProductFeatureDTO::class],
        'reviews' => Collection::class . ':' . ProductReviewDTO::class,
        'user' => UserDTO::class,
    ];

    public function rules(): array
    {
        return [
            'title' => ['required', 'string'],
            'reviews' => ['sometimes', 'required', 'collection', 'min:1'],
        ];
    }
}
```

### ProductDTOAssembler mapping input structure:

[](#productdtoassembler-mapping-input-structure)

```
class ProductDTOAssembler extends ArgonautAssembler
{
    public static function toProductDTO(object $input): ProductDTO
    {
        return new ProductDTO([
            'title' => $input->product_name,
            'user' => $input->user,
            'features' => $input->features ?? [],
            'reviews' => $input->reviews ?? [],
        ]);
    }

    public static function toProductFeatureDTO(object $input): ProductFeatureDTO
    {
        return new ProductFeatureDTO([
            'name' => $input->name ?? 'Unnamed Feature',
            'description' => $input->description ?? null,
        ]);
    }

    public static function toProductReviewDTO(object $input): ProductReviewDTO
    {
        return new ProductReviewDTO([
            'rating' => (int) ($input->rating ?? 0),
            'comment' => $input->comment ?? '',
        ]);
    }
}
```

🎯 Dependency Injection in Assemblers
------------------------------------

[](#-dependency-injection-in-assemblers)

ArgonautAssembler offers enhanced flexibility for your Assembler logic by supporting dependency injection. This allows you to leverage services or custom logic, whether defined in static or non-static methods, during the DTO assembly process. This is particularly powerful when integrating with Laravel's service container.

This feature enables you to:

- **Integrate Application Services:** Easily inject your existing application services (e.g., a custom formatting utility, a validation service) directly into your assembler methods.
- **Decouple Complex Logic:** Keep your assembler methods focused on the core task of data mapping by delegating more complex operations or external data fetching/processing to injected dependencies.
- **Improve Testability:** By injecting dependencies, you can more easily mock them in your unit tests, leading to more robust and isolated tests for your assemblers.

### How Dependency Injection Works

[](#how-dependency-injection-works)

`ArgonautAssembler` supports dependency injection in non-static transformation methods (e.g., `toUserDTO` or `fromUserDTO`) by leveraging Laravel’s service container. When you call `ArgonautAssembler::assemble()`, `fromCollection()`, `fromArray()`, or `assembleInstance()` with an instance of the assembler, the transformation method is invoked on that instance. Laravel’s container automatically resolves and injects any dependencies declared in the method’s signature.

- **Static Methods:** Static transformation methods (e.g., `public static function toUserDTO($input)`) do not support dependency injection, as they are called statically without an instance.
- **Instance Methods:** Non-static transformation methods (e.g., `public function toUserDTO($input)`) are called on an assembler instance, allowing Laravel to inject dependencies into the method.

### Example: Using Dependency Injection

[](#example-using-dependency-injection)

Below is an example of an assembler with a non-static transformation method that uses dependency injection to format a user’s name via an injected service.

```
