Lazy Assertions
Lazy assertions collect multiple validation errors before throwing, allowing you to report all validation failures at once.
Why Lazy Assertions?
Section titled “Why Lazy Assertions?”Traditional assertions fail on the first error:
Assertion::notEmpty($name); // Fails hereAssertion::email($email); // Never checkedAssertion::integer($age); // Never checkedLazy assertions collect all errors:
Assert::lazy() ->that($name, 'name')->notEmpty() ->that($email, 'email')->email() ->that($age, 'age')->integer() ->verifyNow(); // Throws with all errorsBasic Usage
Section titled “Basic Usage”use Cline\Assert\Assert;
Assert::lazy() ->that($email, 'email')->notEmpty()->email() ->that($name, 'name')->notEmpty()->minLength(2) ->that($age, 'age')->integer()->greaterOrEqualThan(18) ->verifyNow();Form Validation
Section titled “Form Validation”User Registration
Section titled “User Registration”$errors = [];
try { Assert::lazy() ->that($data['username'] ?? null, 'username') ->notNull('Username is required') ->notEmpty('Username cannot be empty') ->minLength(3, 'Username must be at least 3 characters') ->that($data['email'] ?? null, 'email') ->notNull('Email is required') ->email('Invalid email format') ->that($data['password'] ?? null, 'password') ->notNull('Password is required') ->minLength(8, 'Password must be at least 8 characters') ->verifyNow();} catch (LazyAssertionException $e) { foreach ($e->getErrorExceptions() as $error) { $errors[$error->getPropertyPath()] = $error->getMessage(); }}API Request Validation
Section titled “API Request Validation”public function validateRequest(array $data): void{ Assert::lazy() ->that($data['action'] ?? null, 'action') ->notNull('Action is required') ->inArray(['create', 'update', 'delete'], 'Invalid action') ->that($data['resource_id'] ?? null, 'resource_id') ->notNull('Resource ID is required') ->uuid('Invalid resource ID format') ->verifyNow();}Configuration Validation
Section titled “Configuration Validation”Assert::lazy() ->that($config['app_name'], 'app_name') ->notEmpty('App name is required') ->that($config['environment'], 'environment') ->inArray(['development', 'staging', 'production']) ->that($config['debug'], 'debug') ->boolean() ->verifyNow();tryAll() Mode
Section titled “tryAll() Mode”By default, lazy assertions stop validating a field after the first failure. Use tryAll() to validate all assertions:
Default Behavior
Section titled “Default Behavior”Assert::lazy() ->that($age, 'age') ->integer() // Fails here for "abc" ->greaterThan(0) // Not checked ->verifyNow();tryAll() Mode
Section titled “tryAll() Mode”Assert::lazy() ->tryAll() ->that($password, 'password') ->string() ->minLength(8) // Check all length requirements ->regex('/[A-Z]/') // Check all complexity requirements ->regex('/[a-z]/') ->regex('/[0-9]/') ->verifyNow(); // Reports ALL failuresError Handling
Section titled “Error Handling”Catching Errors
Section titled “Catching Errors”use Cline\Assert\LazyAssertionException;
try { Assert::lazy() ->that($email, 'email')->email() ->that($age, 'age')->integer() ->verifyNow();} catch (LazyAssertionException $e) { foreach ($e->getErrorExceptions() as $error) { echo $error->getPropertyPath() . ': ' . $error->getMessage() . "\n"; }}JSON API Error Response
Section titled “JSON API Error Response”try { Assert::lazy() ->that($request['email'], 'email')->email() ->verifyNow();} catch (LazyAssertionException $e) { $errors = array_map(function($error) { return [ 'field' => $error->getPropertyPath(), 'message' => $error->getMessage(), ]; }, $e->getErrorExceptions());
return response()->json(['errors' => $errors], 422);}Nested Property Paths
Section titled “Nested Property Paths”Assert::lazy() ->that($user['email'], 'user.email')->email() ->that($user['address']['city'], 'user.address.city')->notEmpty() ->that($user['address']['zip'], 'user.address.zip')->regex('/^\d{5}$/') ->verifyNow();Best Practices
Section titled “Best Practices”Always Use Property Paths
Section titled “Always Use Property Paths”Assert::lazy() ->that($email, 'email')->email() ->that($age, 'age')->integer() ->verifyNow();Use Meaningful Property Paths
Section titled “Use Meaningful Property Paths”Assert::lazy() ->that($email, 'contact_email')->email() ->that($phone, 'contact_phone')->e164() ->verifyNow();Separate Validation from Business Logic
Section titled “Separate Validation from Business Logic”public function createUser(array $data): User{ $this->validateUserData($data); return User::create($data);}
private function validateUserData(array $data): void{ Assert::lazy() ->that($data['email'], 'email')->email() ->verifyNow();}When to Use
Section titled “When to Use”Use lazy assertions when:
- Validating user input (forms, APIs)
- Need to report all errors at once
- Better UX is important
Avoid when:
- Performance-critical code
- Internal validation
- Only one field to validate
Next Steps
Section titled “Next Steps”- Assertion Chains - Single-field validation
- Getting Started - Basic concepts
- Custom Assertions - Custom validation rules