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