An open API service indexing awesome lists of open source software.

https://github.com/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.
https://github.com/yorcreative/laravel-argonaut-dto

archict architecture-patterns backend-development data-transfer-object dto laravel laravel-architecture laravel-dto laravel-package nested-dto object-oriented-programming php-dto serialization service-layer solid-principles validation

Last synced: 28 days ago
JSON representation

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.

Awesome Lists containing this project

README

        







Logo


Laravel Argonaut DTO


GitHub license
GitHub stars
GitHub Org's stars
GitHub issues
GitHub forks
PHPUnit

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`)
- ♻️ Consistent data shape enforcement across boundaries

---

## πŸ“¦ Installation

Install via Composer:

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

---

## πŸš€ Quick Start

### 1. Define a DTO

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

```php
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

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

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

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

---

### 3. Assemble a DTO

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

```php
$dto = UserDTOAssembler::assemble([
'display_name' => 'jdoe',
'email' => '[email protected]',
], UserDTO::class);
```

You can also batch transform arrays or collections:

```php
UserDTOAssembler::fromArray($userArray, UserDTO::class);
UserDTOAssembler::fromCollection($userCollection, UserDTO::class);
```

---

## πŸ§ͺ Real-World Example: Product + Features + Reviews

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

### ProductDTO with nested casting:

```php
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:

```php
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 ?? '',
]);
}
}
```

---

## 🎯 DTOs with Prioritized Attributes and Custom Setters

ArgonautDTO allows you to prioritize the assignment of specific fields using `$prioritizedAttributes`, which is critical for cases where one field influences others.

```php
class UserDTO extends ArgonautDTO
{
public ?string $firstName = null;
public ?string $lastName = null;
public string $username;
public string $email;
public ?string $fullName = null;

protected array $prioritizedAttributes = ['firstName', 'lastName'];

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

public function setFirstName($value)
{
$this->firstName = $value;
$this->fullName = $this->firstName . ' ' . $this->lastName;
}

public function setLastName($value)
{
$this->lastName = $value;
$this->fullName = $this->firstName . ' ' . $this->lastName;
}

public function rules(): array
{
return [
'firstName' => ['nullable', 'string', 'max:32'],
'lastName' => ['nullable', 'string', 'max:32'],
'username' => ['required', 'string', 'max:64'],
'email' => ['required', 'email', 'max:255'],
];
}
}
```

---

## πŸ” Casting Reference

Casting allows you to automatically transform values into other DTOs, Laravel Collections, arrays, dates, and more.

```php
protected array $casts = [
'registeredAt' => \Illuminate\Support\Carbon::class,
'profile' => ProfileDTO::class,
'roles' => [RoleDTO::class],
'permissions' => Collection::class . ':' . PermissionDTO::class,
];
```

| Cast Type | Example | Description |
|------------------------|---------------------------------------------------|--------------------------------------|
| Scalar | `'string'`, `'int'`, etc. | Native PHP type cast |
| Single DTO | `ProfileDTO::class` | Cast an array to a DTO instance |
| Array of DTOs | `[RoleDTO::class]` | Cast to array of DTOs |
| Collection of DTOs | `Collection::class . ':' . CommentDTO::class` | Cast to a Laravel Collection |
| Date casting | `Carbon::class` | Cast to Carbon/DateTime instance |

---

## βœ… Validation

Validate DTOs with Laravel’s validator:

```php
$userDTO->validate(); // Throws ValidationException
$userDTO->validate(false); // Returns array of errors (non-throwing)
$userDTO->isValid(); // Returns true/false
```

---

## πŸ“€ Serialization

Serialize DTOs for output, API responses, etc.

```php
$userDTO->toArray(); // Recursively converts nested DTOs
$userDTO->toJson(); // JSON output (throws on encoding errors)
```

---

## πŸ› οΈ DTO Collection Helper

Create DTO collections directly:

```php
UserDTO::collection([
['username' => 'john', 'email' => '[email protected]'],
]);
```

---

## πŸ§ͺ Testing

Run the test suite using:

```bash
composer test
```

---

## πŸ“š Credits

- [Yorda](https://github.com/yordadev)
- [All Contributors](../../contributors)

---

## πŸ“ƒ License

This package is open-sourced software licensed under the [MIT license](LICENSE).