Both ValidatorBuilder::assert() and ValidatorBuilder::check() throw a ValidationException when validation fails. This exception provides detailed feedback on what went wrong.
The difference between the two methods is that assert() evaluates all validators in the chain and collects every error, while check() stops at the first failure (using ShortCircuit internally).
The ValidationException extends PHP's default InvalidArgumentException. That means you can simply catch InvalidArgumentException.
try {
v::alnum()->assert($input);
} catch (InvalidArgumentException $exception) {
echo $exception->getMessage();
}The same applies to check():
try {
v::alnum()->lowercase()->check($input);
} catch (InvalidArgumentException $exception) {
echo $exception->getMessage(); // Only the first failure
}When an exception is thrown, PHP reports where it was created, not where it was caused. In most validation libraries that means stack traces point deep inside library internals. You end up hunting through the trace to find your actual code.
Although the ValidationException is thrown deep inside Validation's internals, we overwrite the stack trace to provide a helpful message. If v::intType()->assert($input) fails in /opt/example.php line 78, your stack trace looks like this:
Stack trace:
#0 /opt/example.php(78): Respect\Validation\Validator->assert(1.0)
#1 {main}
The getMessage() method returns the message from the first failed validator.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->lowercase()->assert('The Panda');
} catch (ValidationException $exception) {
echo $exception->getMessage();
}The code above generates the following output:
"The Panda" must consist only of letters (a-z) and digits (0-9)
The getFullMessage() method will return a full comprehensive explanation of validators that didn't pass in a nested Markdown list format.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->lowercase()->assert('The Panda');
} catch (ValidationException $exception) {
echo $exception->getFullMessage();
}The code above generates the following output:
- "The Panda" must pass all the rules
- "The Panda" must consist only of letters (a-z) and digits (0-9)
- "The Panda" must consist only of lowercase letters
Retrieve validation messages in array format using getMessages().
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->lowercase()->assert('The Panda');
} catch (ValidationException $exception) {
print_r($exception->getMessages());
}The code above generates the following output:
Array
(
[__root__] => "The Panda" must pass all the rules
[alnum] => "The Panda" must consist only of letters (a-z) and digits (0-9)
[lowercase] => "The Panda" must consist only of lowercase letters
)
When validating with Key or Property, the keys will correspond to the name of the key or property that failed the validation.
You can pass a custom exception as the second argument of ValidatorBuilder::assert() in two ways.
Pass a Throwable to throw a custom exception instead of ValidationException.
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->assert($input, new DomainValidationException('Validation failed!'));
} catch (DomainValidationException $exception) {
echo $exception->getMessage();
}Pass a callable to intercept the ValidationException before throwing your own exception.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->assert(
$input,
fn (ValidationException $exception) => new DomainException(
'Validation error: ' . $exception->getMessage(),
$exception->getCode(),
$exception
)
);
} catch (DomainException $exception) {
echo $exception->getMessage();
}The assert() method accepts different types of templates as the second argument to customize exception messages.
Pass a single string template to replace the root message of the exception.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()->assert('The Panda', 'Invalid username provided');
} catch (ValidationException $exception) {
echo $exception->getFullMessage();
}The code above generates the following output.
- Invalid username provided
Pass custom templates as an array to the assert() method for one-off use cases.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::alnum()
->lowercase()
->assert(
'The Panda',
[
'__root__' => 'The given input is not valid',
'alnum' => 'Your username must consist only of letters and digits',
'lowercase' => 'Your username must be lowercase',
]
);
} catch (ValidationException $exception) {
print_r($exception->getMessages());
}The code above generates the following output.
Array
(
[__root__] => The given input is not valid
[alnum] => Your username must consist only of letters and digits
[lowercase] => Your username must be lowercase
)
Use the Templated validator to attach templates directly to the chain. That way your chain of validators will always have the same template.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::templated('Invalid email address', v::email())
->assert('not an email');
} catch (ValidationException $exception) {
echo $exception->getMessage();
}The code above generates the following output.
Invalid email address
You can also use Templated with template parameters to create dynamic messages.
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\ValidatorBuilder as v;
try {
v::templated(
'The author of the page {{title}} is empty',
v::notBlank(),
['title' => 'Feature Guide']
)->assert('');
} catch (ValidationException $exception) {
echo $exception->getMessage();
}The code above generates the following output.
The author of the page "Feature Guide" is empty