Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConstraintViolationListInterface to Exception in Symfony

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.

like image 722
super.t Avatar asked Dec 13 '22 19:12

super.t


2 Answers

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());
}
like image 108
cn007b Avatar answered Dec 17 '22 05:12

cn007b


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();
    }
like image 20
Miguel A. A. Avatar answered Dec 17 '22 06:12

Miguel A. A.