Examples - Grazulex/laravel-arc GitHub Wiki
๐ซ Examples Gallery
Real-world examples of Laravel Arc DTOs in action. These examples demonstrate practical usage patterns and best practices.
๐ Basic Examples
Simple User DTO
class UserDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: true, validation: 'max:255')]
public string $name;
#[Property(type: 'string', required: true, validation: 'email')]
public string $email;
#[Property(type: 'int', required: true, validation: 'min:0|max:150')]
public int $age;
#[Property(type: 'bool', required: false, default: true)]
public bool $is_active;
}
// Usage
$user = new UserDTO([
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 30
]);
Product DTO with Transformations
use Grazulex\Arc\Transformers\{TrimTransformer, LowercaseTransformer};
class ProductDTO extends LaravelArcDTO
{
#[Property(
type: 'string',
required: true,
transform: [TrimTransformer::class]
)]
public string $name;
#[Property(
type: 'string',
required: false,
transform: [ProductSlugTransformer::class] // Custom transformer from name
)]
public ?string $slug;
#[Property(type: 'float', required: true, validation: 'min:0')]
public float $price;
#[Property(type: 'bool', required: false, default: true)]
public bool $is_available;
}
// Custom slug transformer that generates slug from product name
class ProductSlugTransformer extends SlugTransformer
{
public function __construct()
{
parent::__construct(
sourceField: 'name', // Generate slug from 'name' field
separator: '-',
maxLength: 50
);
}
}
// Usage
$product = new ProductDTO([
'name' => ' Premium Coffee Beans 2025 ',
'price' => 29.99,
'is_available' => true
]);
echo $product->name; // 'Premium Coffee Beans 2025' (trimmed)
echo $product->slug; // 'premium-coffee-beans-2025' (auto-generated)
๐จ Advanced Examples
E-commerce Order System
Order Status Enum
enum OrderStatus: string
{
case PENDING = 'pending';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
case CANCELLED = 'cancelled';
}
Address DTO
class AddressDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: true, validation: 'max:255')]
public string $street;
#[Property(type: 'string', required: true, validation: 'max:100')]
public string $city;
#[Property(type: 'string', required: true, validation: 'max:20')]
public string $postal_code;
#[Property(
type: 'string',
required: true,
validation: 'size:2',
transform: [UppercaseTransformer::class]
)]
public string $country_code;
}
Order Item DTO
class OrderItemDTO extends LaravelArcDTO
{
#[Property(type: 'int', required: true)]
public int $product_id;
#[Property(type: 'string', required: true, validation: 'max:255')]
public string $product_name;
#[Property(type: 'int', required: true, validation: 'min:1')]
public int $quantity;
#[Property(type: 'float', required: true, validation: 'min:0')]
public float $unit_price;
public function getTotalPrice(): float
{
return $this->quantity * $this->unit_price;
}
}
Complete Order DTO
class OrderDTO extends LaravelArcDTO
{
#[Property(type: 'string', required: true)]
public string $order_number;
#[Property(type: 'int', required: true)]
public int $customer_id;
#[Property(type: 'nested', class: AddressDTO::class, required: true)]
public AddressDTO $shipping_address;
#[Property(type: 'nested', class: AddressDTO::class, required: true)]
public AddressDTO $billing_address;
#[Property(type: 'collection', class: OrderItemDTO::class, required: true, validation: 'min:1')]
public array $items;
#[Property(type: 'enum', class: OrderStatus::class, default: OrderStatus::PENDING)]
public OrderStatus $status;
#[Property(type: 'date', required: false)]
public ?Carbon $created_at;
public function getTotalAmount(): float
{
return array_sum(array_map(fn($item) => $item->getTotalPrice(), $this->items));
}
public function getItemCount(): int
{
return array_sum(array_map(fn($item) => $item->quantity, $this->items));
}
}
Blog System
User Role Enum
enum UserRole: string
{
case ADMIN = 'admin';
case EDITOR = 'editor';
case AUTHOR = 'author';
case SUBSCRIBER = 'subscriber';
}
Author DTO
class AuthorDTO extends LaravelArcDTO
{
#[Property(type: 'int', required: true)]
public int $id;
#[Property(type: 'string', required: true, validation: 'max:255')]
public string $name;
#[Property(
type: 'string',
required: true,
validation: 'email',
transform: [TrimTransformer::class, LowercaseTransformer::class]
)]
public string $email;
#[Property(type: 'enum', class: UserRole::class, default: UserRole::AUTHOR)]
public UserRole $role;
#[Property(type: 'string', required: false)]
public ?string $bio;
}
Category DTO
class CategoryDTO extends LaravelArcDTO
{
#[Property(type: 'int', required: true)]
public int $id;
#[Property(
type: 'string',
required: true,
validation: 'max:100',
transform: [TrimTransformer::class]
)]
public string $name;
#[Property(
type: 'string',
required: true,
transform: [
TrimTransformer::class,
LowercaseTransformer::class,
SlugTransformer::class
]
)]
public string $slug;
#[Property(type: 'string', required: false)]
public ?string $description;
}
Blog Post DTO
class BlogPostDTO extends LaravelArcDTO
{
#[Property(type: 'int', required: false)]
public ?int $id;
#[Property(
type: 'string',
required: true,
validation: 'max:255',
transform: [TrimTransformer::class]
)]
public string $title;
#[Property(
type: 'string',
required: true,
transform: [
TrimTransformer::class,
LowercaseTransformer::class,
SlugTransformer::class
]
)]
public string $slug;
#[Property(type: 'string', required: true)]
public string $content;
#[Property(type: 'string', required: false)]
public ?string $excerpt;
#[Property(type: 'nested', class: AuthorDTO::class, required: true)]
public AuthorDTO $author;
#[Property(type: 'collection', class: CategoryDTO::class, required: false, default: [])]
public array $categories;
#[Property(type: 'array', required: false, default: [])]
public array $tags;
#[Property(type: 'bool', required: false, default: false)]
public bool $is_published;
#[Property(type: 'date', required: false)]
public ?Carbon $published_at;
#[Property(type: 'date', required: false)]
public ?Carbon $created_at;
#[Property(type: 'date', required: false)]
public ?Carbon $updated_at;
}
๐ง Service Layer Integration
User Service
class UserService
{
public function __construct(
private UserRepository $userRepository
) {}
public function createUser(CreateUserDTO $dto): UserDTO
{
$user = $this->userRepository->create($dto->toArray());
return new UserDTO([
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'created_at' => $user->created_at
]);
}
public function updateUser(int $id, UpdateUserDTO $dto): UserDTO
{
$user = $this->userRepository->findOrFail($id);
$user->update($dto->toArray());
return new UserDTO($user->toArray());
}
}
Order Service
class OrderService
{
public function createOrder(CreateOrderDTO $dto): OrderDTO
{
DB::transaction(function () use ($dto) {
// Create order
$order = Order::create([
'order_number' => $this->generateOrderNumber(),
'customer_id' => $dto->customer_id,
'status' => OrderStatus::PENDING
]);
// Create order items
foreach ($dto->items as $itemDto) {
$order->items()->create($itemDto->toArray());
}
// Create addresses
$order->shippingAddress()->create($dto->shipping_address->toArray());
$order->billingAddress()->create($dto->billing_address->toArray());
return $order;
});
}
}
๐๏ธ Controller Examples
API Controller
class UserController extends Controller
{
public function store(Request $request): JsonResponse
{
// Validate using DTO rules
$validated = $request->validate(CreateUserDTO::rules());
// Create DTO
$userDto = new CreateUserDTO($validated);
// Process through service
$createdUser = $this->userService->createUser($userDto);
return response()->json($createdUser->toArray(), 201);
}
public function update(Request $request, int $id): JsonResponse
{
$validated = $request->validate(UpdateUserDTO::rules());
$userDto = new UpdateUserDTO($validated);
$updatedUser = $this->userService->updateUser($id, $userDto);
return response()->json($updatedUser->toArray());
}
}
Form Request Integration
class CreateUserRequest extends FormRequest
{
public function rules(): array
{
return CreateUserDTO::rules();
}
public function toDTO(): CreateUserDTO
{
return new CreateUserDTO($this->validated());
}
}
// In controller
class UserController extends Controller
{
public function store(CreateUserRequest $request): JsonResponse
{
$userDto = $request->toDTO();
$createdUser = $this->userService->createUser($userDto);
return response()->json($createdUser->toArray(), 201);
}
}
๐งช Testing Examples
DTO Testing
class UserDTOTest extends TestCase
{
public function test_creates_user_dto_with_valid_data(): void
{
$data = [
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 30
];
$user = new UserDTO($data);
$this->assertEquals('John Doe', $user->name);
$this->assertEquals('[email protected]', $user->email);
$this->assertEquals(30, $user->age);
$this->assertTrue($user->is_active); // Default value
}
public function test_transforms_email_to_lowercase(): void
{
$user = new UserDTO([
'name' => 'John Doe',
'email' => '[email protected]',
'age' => 30
]);
$this->assertEquals('[email protected]', $user->email);
}
public function test_validates_required_fields(): void
{
$this->expectException(ValidationException::class);
new UserDTO([
'email' => '[email protected]'
// Missing required 'name' field
]);
}
}
Factory Testing
class UserDTOFactory
{
public static function make(array $attributes = []): UserDTO
{
return new UserDTO(array_merge([
'name' => fake()->name(),
'email' => fake()->email(),
'age' => fake()->numberBetween(18, 65),
'is_active' => true
], $attributes));
}
public static function makeInactive(): UserDTO
{
return self::make(['is_active' => false]);
}
public static function makeAdmin(): UserDTO
{
return self::make([
'email' => '[email protected]',
'role' => UserRole::ADMIN
]);
}
}
// Usage in tests
class UserServiceTest extends TestCase
{
public function test_creates_user_successfully(): void
{
$userDto = UserDTOFactory::make();
$createdUser = $this->userService->createUser($userDto);
$this->assertInstanceOf(UserDTO::class, $createdUser);
$this->assertEquals($userDto->email, $createdUser->email);
}
}
๐ฐ๏ธ Migration Examples
From v1 to v2 Syntax
Before (v1.x)
class UserDTO extends LaravelArcDTO
{
#[DateProperty(required: true)]
public Carbon $created_at;
#[EnumProperty(enumClass: UserStatus::class)]
public UserStatus $status;
#[NestedProperty(dtoClass: AddressDTO::class)]
public AddressDTO $address;
}
After (v2.x)
class UserDTO extends LaravelArcDTO
{
#[Property(type: 'date', required: true)]
public Carbon $created_at;
#[Property(type: 'enum', class: UserStatus::class)]
public UserStatus $status;
#[Property(type: 'nested', class: AddressDTO::class)]
public AddressDTO $address;
}
๐ Related Pages
- Quick Start - Get started with basic examples
- Property Attributes - Learn all attribute options
- Advanced Features - Explore advanced capabilities
- Best Practices - Recommended patterns
- Migration Guide - Upgrade from v1 to v2
โฌ ๏ธ Back to: Home | โก๏ธ Next: Best Practices