Validation
Learn how to validate DTOs using automatic rule inferring and validation attributes.
What is Validation?
Section titled “What is Validation?”Validation ensures that data meets specific requirements before being processed. SimpleDTO provides:
- Automatic rule inferring from types and attributes
- 30+ validation attributes
- Framework integration (Laravel, Symfony)
- Custom validation rules
- Validation caching (198x faster)
Quick Start
Section titled “Quick Start”Basic Validation
Section titled “Basic Validation”use Event4u\DataHelpers\SimpleDTO;use Event4u\DataHelpers\SimpleDTO\Attributes\Required;use Event4u\DataHelpers\SimpleDTO\Attributes\Email;use Event4u\DataHelpers\SimpleDTO\Attributes\Between;
class UserDTO extends SimpleDTO{ public function __construct( #[Required] public readonly string $name,
#[Required, Email] public readonly string $email,
#[Required, Between(18, 120)] public readonly int $age, ) {}}
// Validate and create$dto = UserDTO::validateAndCreate([ 'name' => 'John Doe', 'email' => 'john@example.com', 'age' => 30,]);Handling Validation Errors
Section titled “Handling Validation Errors”use Event4u\DataHelpers\SimpleDTO\Exceptions\ValidationException;
try { $dto = UserDTO::validateAndCreate([ 'name' => '', // ❌ Required 'email' => 'invalid', // ❌ Invalid email 'age' => 15, // ❌ Too young ]);} catch (ValidationException $e) { echo $e->getMessage(); print_r($e->errors());}Validation Attributes
Section titled “Validation Attributes”Required Validation
Section titled “Required Validation”use Event4u\DataHelpers\SimpleDTO\Attributes\Required;
class UserDTO extends SimpleDTO{ public function __construct( #[Required] public readonly string $name,
#[Required] public readonly string $email,
// Optional - no Required attribute public readonly ?string $phone = null, ) {}}String Validation
Section titled “String Validation”use Event4u\DataHelpers\SimpleDTO\Attributes\StringType;use Event4u\DataHelpers\SimpleDTO\Attributes\Min;use Event4u\DataHelpers\SimpleDTO\Attributes\Max;use Event4u\DataHelpers\SimpleDTO\Attributes\Between;
class PostDTO extends SimpleDTO{ public function __construct( #[Required, StringType, Min(3)] public readonly string $title,
#[Required, StringType, Between(10, 1000)] public readonly string $content,
#[StringType, Max(100)] public readonly ?string $excerpt = null, ) {}}Numeric Validation
Section titled “Numeric Validation”use Event4u\DataHelpers\SimpleDTO\Attributes\IntegerType;use Event4u\DataHelpers\SimpleDTO\Attributes\Numeric;use Event4u\DataHelpers\SimpleDTO\Attributes\Min;use Event4u\DataHelpers\SimpleDTO\Attributes\Max;
class ProductDTO extends SimpleDTO{ public function __construct( #[Required, IntegerType, Min(1)] public readonly int $quantity,
#[Required, Numeric, Min(0)] public readonly float $price,
#[IntegerType, Between(0, 100)] public readonly ?int $discount = null, ) {}}Email Validation
Section titled “Email Validation”use Event4u\DataHelpers\SimpleDTO\Attributes\Email;
class ContactDTO extends SimpleDTO{ public function __construct( #[Required, Email] public readonly string $email,
#[Email] public readonly ?string $alternativeEmail = null, ) {}}URL Validation
Section titled “URL Validation”use Event4u\DataHelpers\SimpleDTO\Attributes\Url;
class WebsiteDTO extends SimpleDTO{ public function __construct( #[Required, Url] public readonly string $website,
#[Url] public readonly ?string $blog = null, ) {}}All Validation Attributes
Section titled “All Validation Attributes”| Attribute | Description | Example |
|---|---|---|
Required | Field is required | #[Required] |
Email | Valid email address | #[Email] |
Url | Valid URL | #[Url] |
Min | Minimum value/length | #[Min(3)] |
Max | Maximum value/length | #[Max(100)] |
Between | Value between min and max | #[Between(18, 120)] |
StringType | Must be string | #[StringType] |
IntegerType | Must be integer | #[IntegerType] |
Numeric | Must be numeric | #[Numeric] |
BooleanType | Must be boolean | #[BooleanType] |
ArrayType | Must be array | #[ArrayType] |
In | Value in list | #[In(['active', 'inactive'])] |
NotIn | Value not in list | #[NotIn(['banned'])] |
Regex | Matches regex | #[Regex('/^[A-Z]/')] |
Alpha | Only letters | #[Alpha] |
AlphaNum | Letters and numbers | #[AlphaNum] |
AlphaDash | Letters, numbers, dashes | #[AlphaDash] |
Uuid | Valid UUID | #[Uuid] |
Json | Valid JSON | #[Json] |
Date | Valid date | #[Date] |
DateFormat | Date in format | #[DateFormat('Y-m-d')] |
Before | Date before | #[Before('2024-12-31')] |
After | Date after | #[After('2024-01-01')] |
Ip | Valid IP address | #[Ip] |
Ipv4 | Valid IPv4 | #[Ipv4] |
Ipv6 | Valid IPv6 | #[Ipv6] |
MacAddress | Valid MAC address | #[MacAddress] |
Timezone | Valid timezone | #[Timezone] |
Unique | Unique in database | #[Unique('users', 'email')] |
Exists | Exists in database | #[Exists('users', 'id')] |
Custom Validation
Section titled “Custom Validation”Creating Custom Validator
Section titled “Creating Custom Validator”use Event4u\DataHelpers\SimpleDTO\Contracts\ValidationRule;
class EvenNumber implements ValidationRule{ public function passes(mixed $value): bool { return is_int($value) && $value % 2 === 0; }
public function message(): string { return 'The value must be an even number.'; }}
class NumberDTO extends SimpleDTO{ public function __construct( #[EvenNumber] public readonly int $number, ) {}}Framework Integration
Section titled “Framework Integration”Laravel Validation
Section titled “Laravel Validation”// Automatic Laravel validationclass UserController extends Controller{ public function store(Request $request) { $dto = UserDTO::validateAndCreate($request->all()); // Automatically uses Laravel's validator }}Symfony Validation
Section titled “Symfony Validation”// Automatic Symfony validationclass UserController{ public function store(Request $request) { $dto = UserDTO::validateAndCreate($request->request->all()); // Automatically uses Symfony's validator }}Validation Caching
Section titled “Validation Caching”SimpleDTO caches validation rules for 198x faster performance:
// First call - builds and caches rules$dto1 = UserDTO::validateAndCreate($data1); // ~10ms
// Subsequent calls - uses cached rules$dto2 = UserDTO::validateAndCreate($data2); // ~0.05ms (198x faster!)Best Practices
Section titled “Best Practices”Combine Multiple Attributes
Section titled “Combine Multiple Attributes”// ✅ Good - multiple validation rules#[Required, StringType, Min(3), Max(50), Alpha]public readonly string $name;Use Type Hints with Validation
Section titled “Use Type Hints with Validation”// ✅ Good - type hint + validation#[Required, Between(18, 120)]public readonly int $age;
// ❌ Bad - no type hint#[Required, Between(18, 120)]public readonly $age;Validate Early
Section titled “Validate Early”// ✅ Good - validate at creation$dto = UserDTO::validateAndCreate($data);
// ❌ Bad - create then validate$dto = UserDTO::fromArray($data);$dto->validate();Code Examples
Section titled “Code Examples”The following working examples demonstrate this feature:
- Basic Validation - Simple validation rules
- Advanced Validation - Complex validation scenarios
- Request Validation Core - Core request validation
- Laravel Validation - Laravel integration
- Symfony Validation - Symfony integration
- Validation Modes - Different validation modes
- Nested Validation - Validating nested DTOs
All examples are fully tested and can be run directly.
Related Tests
Section titled “Related Tests”The functionality is thoroughly tested. Key test files:
- ValidationModesTest.php - Validation mode tests
- ValidationTest.php - Core validation tests
- NestedValidationTest.php - Nested validation tests
Run the tests:
# Run teststask test:unit -- --filter=ValidationSee Also
Section titled “See Also”- Type Casting - Automatic type conversion
- Creating DTOs - Creation methods
- Property Mapping - Map property names