Basic Usage - Grazulex/laravel-arc GitHub Wiki
🚀 Basic Usage
Overview
Laravel Arc is a powerful package for creating Data Transfer Objects (DTOs) in Laravel using PHP 8+ attributes. This guide covers the fundamental concepts and basic usage patterns for building type-safe, validated DTOs.
Getting Started
1. Basic DTO Setup
Create a DTO by extending LaravelArcDTO
and using the Property
attribute:
<?php
namespace App\DTOs;
use Grazulex\Arc\LaravelArcDTO;
use Grazulex\Arc\Attributes\Property;
class UserDTO extends LaravelArcDTO
{
#[Property(
type: 'string',
required: true,
validation: 'max:100'
)]
public string $name;
#[Property(
type: 'string',
required: true,
validation: 'email'
)]
public string $email;
#[Property(
type: 'int',
required: false,
validation: 'min:18|max:120'
)]
public ?int $age = null;
}
2. Creating and Using DTOs
// Create a DTO with data
$user = new UserDTO([
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 30
]);
// Access properties directly
echo $user->name; // 'John Doe'
echo $user->email; // '[email protected]'
echo $user->age; // 30
// Modify properties with automatic validation
$user->age = 31; // Will validate that 31 is between 18-120
$user->name = 'John Smith';
// Convert to array
$array = $user->toArray();
// Convert to JSON
$json = $user->toJson();
3. Validation
Validation happens automatically based on your property attributes:
use Grazulex\Arc\Exceptions\InvalidDTOException;
try {
$user = new UserDTO([
'name' => '', // Will fail - required field
'email' => 'invalid-email', // Will fail - not valid email
'age' => 150 // Will fail - exceeds max of 120
]);
} catch (InvalidDTOException $e) {
echo $e->getMessage();
}
Core Concepts
Supported Property Types
Laravel Arc supports these property types in the Property
attribute:
use Carbon\Carbon;
use Grazulex\Arc\LaravelArcDTO;
use Grazulex\Arc\Attributes\Property;
class ExampleDTO extends LaravelArcDTO
{
// String properties
#[Property(type: 'string', required: true, validation: 'max:255')]
public string $title;
// Numeric properties
#[Property(type: 'int', required: true, validation: 'min:0')]
public int $count;
#[Property(type: 'float', required: true, validation: 'min:0|max:100')]
public float $percentage;
// Boolean properties
#[Property(type: 'bool', required: false, default: false)]
public bool $is_active;
// Date properties
#[Property(type: 'date', required: false)]
public ?Carbon $created_at = null;
// Array properties
#[Property(type: 'array', required: false, default: [])]
public array $tags;
// Enum support
#[Property(type: 'enum', class: UserStatus::class)]
public UserStatus $status;
// Nested DTOs
#[Property(type: 'nested', class: AddressDTO::class)]
public AddressDTO $address;
// Collections of DTOs
#[Property(type: 'collection', class: OrderItemDTO::class)]
public array $items;
}
Required vs Optional Properties
class UserDTO extends LaravelArcDTO
{
// Required property (will validate as required)
#[Property(type: 'string', required: true)]
public string $name;
// Optional property (nullable)
#[Property(type: 'string', required: false)]
public ?string $nickname = null;
// Optional with default value
#[Property(type: 'bool', required: false, default: true)]
public bool $is_active = true;
}
Default Values
class SettingsDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: false, default: 'en')]
public string $language = 'en';
#[Property(type: 'int', required: false, default: 10)]
public int $page_size = 10;
#[Property(type: 'array', required: false, default: [])]
public array $preferences = [];
}
Advanced Features
Data Transformation
Use transformers to process data before casting:
use Grazulex\Arc\Transformers\TrimTransformer;
use Grazulex\Arc\Transformers\LowercaseTransformer;
class UserDTO extends LaravelArcDTO
{
#[Property(
type: 'string',
required: true,
transform: [TrimTransformer::class, LowercaseTransformer::class]
)]
public string $email; // ' [email protected] ' becomes '[email protected]'
}
Enum Support
enum UserStatus: string
{
case ACTIVE = 'active';
case INACTIVE = 'inactive';
case PENDING = 'pending';
}
class UserDTO extends LaravelArcDTO
{
#[Property(type: 'enum', class: UserStatus::class)]
public UserStatus $status; // 'active' becomes UserStatus::ACTIVE
}
Nested DTOs and Collections
class AddressDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: true)]
public string $street;
#[Property(type: 'string', required: true)]
public string $city;
}
class UserDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: true)]
public string $name;
// Nested DTO
#[Property(type: 'nested', class: AddressDTO::class)]
public AddressDTO $address;
// Collection of DTOs
#[Property(type: 'collection', class: AddressDTO::class)]
public array $addresses;
}
$user = new UserDTO([
'name' => 'John',
'address' => [
'street' => '123 Main St',
'city' => 'Paris'
],
'addresses' => [
['street' => '123 Main St', 'city' => 'Paris'],
['street' => '456 Oak Ave', 'city' => 'Lyon']
]
]);
Model to DTO Conversion
Convert Eloquent models to DTOs using the DTOFromModelTrait
:
use Grazulex\Arc\Traits\DTOFromModelTrait;
class UserDTO extends LaravelArcDTO
{
use DTOFromModelTrait;
#[Property(type: 'string', required: true)]
public string $name;
#[Property(type: 'string', required: true, validation: 'email')]
public string $email;
}
// Convert single model
$user = User::find(1);
$userDTO = UserDTO::fromModel($user);
// Convert collection
$users = User::all();
$userDTOs = UserDTO::fromModels($users);
See Model to DTO Conversion for detailed documentation.
Factory Usage
Laravel Arc includes a powerful factory system:
// Generate fake data
$fakeUser = UserDTO::fake();
// Generate multiple DTOs
$users = UserDTO::fakeMany(5);
// Customize specific fields
$customUser = UserDTO::factory()
->with('name', 'John Doe')
->with('email', '[email protected]')
->fake()
->create();
Artisan Commands
Generate DTOs automatically with the make:dto
command:
# Basic DTO generation
php artisan make:dto User
# Generate from existing model
php artisan make:dto User --model=User
# With relations and validation
php artisan make:dto User --model=User --with-relations --with-validation
# Analyze DTO structure
php artisan dto:analyze UserDTO
# Validate data against DTO
php artisan dto:validate UserDTO --data='{"name":"John"}'
Usage Patterns
API Endpoints
class UserController extends Controller
{
public function store(Request $request)
{
// Create DTO from request data with automatic validation
$userDTO = new UserDTO($request->all());
// Use DTO data to create model
$user = User::create($userDTO->toArray());
return response()->json($user, 201);
}
}
Service Layer
class UserService
{
public function createUser(UserDTO $userDTO): User
{
// DTO is already validated at this point
return User::create($userDTO->toArray());
}
public function updateUser(User $user, UserDTO $userDTO): User
{
$user->update($userDTO->toArray());
return $user->fresh();
}
}
Form Processing
class CreateUserRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
// Generate rules from DTO
return UserDTO::rules();
}
public function toDTO(): UserDTO
{
return new UserDTO($this->validated());
}
}
Error Handling
use Grazulex\Arc\Exceptions\InvalidDTOException;
try {
$user = new UserDTO([
'name' => '', // Invalid - required
'email' => 'not-an-email', // Invalid format
'age' => 150, // Invalid - exceeds max
]);
} catch (InvalidDTOException $e) {
// Handle validation errors
$message = $e->getMessage();
$field = $e->getField(); // Which field caused the error
$value = $e->getValue(); // The invalid value
}
Next Steps
Now that you understand the basics of Laravel Arc DTOs:
- 🎯 Explore Property Attributes for advanced configuration
- ✨ Learn about Advanced Features like transformations and enums
- 🏭 Check out MakeDtoCommand for auto-generation
- 📚 Browse Examples for real-world usage patterns
- 🔄 Read the Migration Guide if upgrading from v1
🚀 Ready to build type-safe, validated DTOs? Laravel Arc makes data handling elegant and robust!