I need to convert an object of type ConstraintViolationListInterface
to a single exception for further logging, where the message is a concatenation of the messages from each constraint violation on the list, when the validation fails.
Obviously I can't repeat a foreach loop in every bundle using validation to achieve this, therefore I was thinking about creating one more bundle providing a simple service accepting ConstraintViolationListInterface
and returning a single exception. Is there a standard solution for this in Symfony? Seems weird that I need to write this service, the problem seems to be common to me.
I also was surprised that symfony has nothing helpful for this, that's why I've created my custom exception:
class ValidationException extends \Exception
{
private $violations;
public function __construct(array $violations)
{
$this->violations = $violations;
parent::__construct('Validation failed.');
}
public function getMessages()
{
$messages = [];
foreach ($this->violations as $paramName => $violationList) {
foreach ($violationList as $violation) {
$messages[$paramName][] = $violation->getMessage();
}
}
return $messages;
}
public function getJoinedMessages()
{
$messages = [];
foreach ($this->violations as $paramName => $violationList) {
foreach ($violationList as $violation) {
$messages[$paramName][] = $violation->getMessage();
}
$messages[$paramName] = implode(' ', $messages[$paramName]);
}
return $messages;
}
}
All code available here.
And I use this exception in a next way:
try {
$errors = $validator->validate(...);
if (0 !== count($errors)) {
throw new ValidationException($errors);
}
} catch (ValidationException $e) {
// Here you can obtain your validation errors.
var_dump($e->getMessages());
}
This solution works fine for me:
protected function violationsToArray(ConstraintViolationListInterface $violations)
{
$messages = [];
foreach ($violations as $constraint) {
$prop = $constraint->getPropertyPath();
$messages[$prop][] = $constraint->getMessage();
}
return $messages;
}
Note that using $violations array keys as property names will not work:
$messages = [];
foreach ($violations as $prop => $constraint) {
// $prop will not contain any value and this will not work as expected
$messages[$prop][] = $constraint->getMessage();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With