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.
- Host: GitHub
- URL: https://github.com/yorcreative/laravel-argonaut-dto
- Owner: YorCreative
- License: mit
- Created: 2025-04-20T16:26:17.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2025-04-20T16:39:57.000Z (about 1 month ago)
- Last Synced: 2025-04-20T17:39:26.585Z (about 1 month ago)
- Topics: 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
- Language: PHP
- Homepage:
- Size: 630 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
Laravel Argonaut DTO
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).