-
-
Notifications
You must be signed in to change notification settings - Fork 0
Example API Integration
A comprehensive real-world example showing how to use Laravel Arc DTOs in modern API controllers with behavioral traits and validation.
This example is based on the actual code from examples/modern-api-controller-example.php:
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api;
use App\DTO\UserDTO;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
final class UserController extends Controller
{
/**
* Display a listing of users with DTO transformation
*/
public function index(Request $request): JsonResponse
{
$users = User::query()
->when($request->search, function ($query, $search) {
$query->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
})
->when($request->status, function ($query, $status) {
$query->where('status', $status);
})
->paginate($request->per_page ?? 15);
// Transform to DTOs with behavioral traits
$userDtos = $users->getCollection()->map(function ($user) {
return UserDTO::fromModel($user);
});
return response()->json([
'data' => $userDtos,
'pagination' => [
'current_page' => $users->currentPage(),
'last_page' => $users->lastPage(),
'per_page' => $users->perPage(),
'total' => $users->total(),
],
]);
}
/**
* Store a newly created user with comprehensive validation
*/
public function store(Request $request): JsonResponse
{
// Use ValidatesData trait for validation
if (UserDTO::fails($request->all())) {
return response()->json([
'message' => 'Validation failed',
'errors' => UserDTO::validator($request->all())->errors(),
], 422);
}
// Create user with validated data
$validated = UserDTO::validate($request->all());
$user = User::create($validated);
// Convert to DTO and demonstrate behavioral traits
$userDto = UserDTO::fromModel($user);
// Use HasTagging trait if available
if (method_exists($userDto, 'addTag')) {
$userDto = $userDto->addTag('new_user');
}
// Use HasAuditing trait if available
if (method_exists($userDto, 'setCreator')) {
$userDto = $userDto->setCreator(auth()->id());
}
return response()->json([
'message' => 'User created successfully',
'user' => $userDto->toArray(),
], 201);
}
/**
* Display the specified user
*/
public function show(User $user): JsonResponse
{
$userDto = UserDTO::fromModel($user);
return response()->json([
'user' => $userDto->toArray(),
]);
}
/**
* Update the specified user
*/
public function update(Request $request, User $user): JsonResponse
{
// Validate with DTO
$validated = UserDTO::validate($request->all());
// Update model
$user->update($validated);
// Convert to DTO
$userDto = UserDTO::fromModel($user->fresh());
// Use HasTimestamps trait
if (method_exists($userDto, 'touch')) {
$userDto->touch(); // Updates updated_at
}
return response()->json([
'message' => 'User updated successfully',
'user' => $userDto->toArray(),
]);
}
/**
* Remove the specified user (soft delete)
*/
public function destroy(User $user): JsonResponse
{
$userDto = UserDTO::fromModel($user);
// Soft delete the user
$user->delete();
return response()->json([
'message' => 'User deleted successfully',
'user' => $userDto->toArray(),
]);
}
}The corresponding YAML definition (examples/user.yaml):
# API User DTO with behavioral traits
header:
dto: UserDTO
table: users
model: App\Models\User
namespace: App\DTO
traits:
- HasUuid
- HasTimestamps
- ValidatesData
- ConvertsData
use:
- App\DTO\ProfileDTO
fields:
name:
type: string
required: true
validation: [required, string, min:2, max:100]
transformers: [trim, title_case]
email:
type: string
required: true
validation: [required, email, unique:users]
transformers: [trim, lowercase]
email_verified_at:
type: datetime
required: false
validation: [nullable, date]
status:
type: string
required: false
validation: [nullable, in:active,inactive,pending]
default: "active"
# Profile as nested DTO
profile:
type: dto
dto: ProfileDTO
required: false
relations:
posts:
type: hasMany
target: App\Models\Post
roles:
type: belongsToMany
target: App\Models\Role// Instead of manual validation rules
$request->validate([
'name' => 'required|string|min:2|max:100',
'email' => 'required|email|unique:users',
]);
// Use DTO validation
if (UserDTO::fails($request->all())) {
return response()->json([
'errors' => UserDTO::validator($request->all())->errors(),
], 422);
}// DTOs ensure consistent output format
return response()->json([
'user' => $userDto->toArray(), // Always consistent structure
]);// Type-safe property access
$userName = $userDto->name; // string
$userEmail = $userDto->email; // string
$verified = $userDto->email_verified_at; // ?DateTime// Use behavioral traits methods
if (method_exists($userDto, 'wasRecentlyCreated')) {
$isNew = $userDto->wasRecentlyCreated(); // boolean
}
if (method_exists($userDto, 'touch')) {
$userDto->touch(); // Updates timestamp
}public function bulkStore(Request $request): JsonResponse
{
$users = collect($request->users)->map(function ($userData) {
// Validate each user
$validated = UserDTO::validate($userData);
$user = User::create($validated);
return UserDTO::fromModel($user);
});
return response()->json([
'message' => 'Users created successfully',
'users' => $users->toArray(),
'count' => $users->count(),
], 201);
}public function search(Request $request): JsonResponse
{
$users = User::query()
->when($request->name, fn($q, $name) =>
$q->where('name', 'like', "%{$name}%"))
->when($request->email, fn($q, $email) =>
$q->where('email', 'like', "%{$email}%"))
->when($request->status, fn($q, $status) =>
$q->where('status', $status))
->get();
$userDtos = $users->map(fn($user) => UserDTO::fromModel($user));
return response()->json([
'users' => $userDtos->toArray(),
'total' => $userDtos->count(),
]);
}public function export(Request $request): JsonResponse
{
$users = User::all();
$userDtos = $users->map(fn($user) => UserDTO::fromModel($user));
// Use DTO export capabilities
$format = $request->format ?? 'json';
switch ($format) {
case 'csv':
$content = $userDtos->toCsv();
break;
case 'xml':
$content = $userDtos->toXml();
break;
default:
$content = $userDtos->toJson();
}
return response($content)
->header('Content-Type', "application/{$format}")
->header('Content-Disposition', "attachment; filename=users.{$format}");
}// routes/api.php
Route::apiResource('users', UserController::class);
Route::post('users/bulk', [UserController::class, 'bulkStore']);
Route::get('users/search', [UserController::class, 'search']);
Route::get('users/export', [UserController::class, 'export']);# Create user
curl -X POST /api/users \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "[email protected]",
"status": "active"
}'
# Get user
curl -X GET /api/users/1
# Search users
curl -X GET "/api/users/search?name=John&status=active"
# Export users as CSV
curl -X GET "/api/users/export?format=csv"{
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "John Doe",
"email": "[email protected]",
"email_verified_at": null,
"status": "active",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"profile": null
}
}public function store(Request $request): JsonResponse
{
try {
// Validate with DTO
$validated = UserDTO::validate($request->all());
// Create user
$user = User::create($validated);
$userDto = UserDTO::fromModel($user);
return response()->json([
'message' => 'User created successfully',
'user' => $userDto->toArray(),
], 201);
} catch (ValidationException $e) {
return response()->json([
'message' => 'Validation failed',
'errors' => $e->errors(),
], 422);
} catch (\Exception $e) {
return response()->json([
'message' => 'Server error',
'error' => $e->getMessage(),
], 500);
}
}This example shows Laravel Arc in a real API context. Explore more:
- Behavioral Traits - Learn about HasTimestamps, HasUuid, etc.
- Collections - Handle arrays of DTOs
- Field Transformers - Automatic data cleaning
- Generated DTO Structure - Understanding the generated code
This real-world example demonstrates how Laravel Arc DTOs provide type safety, validation, and consistency in modern API development. π
Laravel Arc - Generate Type-Safe DTOs from YAML Definitions
π Home | π Get Started | π Examples | βοΈ Config
From YAML to Type-Safe Code - Made with β€οΈ for the Laravel community
π Home
- π Understanding YAML Structure
- π·οΈ Field Types
- π Field Transformers
- π Behavioral Traits
YAML β DTO β Type-Safe Code
Laravel Arc transforms your YAML definitions into powerful PHP DTOs with automatic validation, field transformers, and behavioral traits.
- π Get Started - Create your first DTO in 5 minutes
- π All Examples - Copy-paste ready examples
- β‘ Commands - CLI reference