phpsymfonyvalidationsymfony-validator

Handle Entity classes with Symfony Validator component


I'm trying to use symfony/validator outside of Symfony by just installing composer require symfony/validator (vemphasized text7.1)

Following this guide https://symfony.com/doc/current/components/validator.html

I now have:

$validator = Validation::createValidator();
$violations = $validator->validate($someName, [
    new Length(['min' => 10]),
    new NotBlank(),
]);

This validation works fine.

But I would like validation like in this guide: https://symfony.com/doc/current/validation.html So that I can validate something like this:

// src/Entity/Author.php
<?php

namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    #[Assert\NotBlank]
    public string $name;
}

When I now try to validate it $violations is always 0 even if the name is null

    $author = new Author();
    $author->name = null;
    $validator = Validation::createValidator();
    $violations = $validator->validate($author);

The documentation isn't very clear on this but it looks like the standalone version is incapable of handling a class like this.

Is something like this possible with the standalone version?


Solution

  • Turned out that creating function that does the same trick wasn't that hard to make:

    function validateEntity($entity)
    {
        $class = new ReflectionClass($entity);
    
        $validator = Validation::createValidator();
    
        $violations = [];
        $properties = $class->getProperties();
        foreach ($properties as $property) {
            $propertyName = $property->getName();
            $attributes = $property->getAttributes();
            $constraints = [];
            foreach ($attributes as $attribute) {
                $constraints[] = $attribute->newInstance();
            }
    
            try {
                $value = $entity->$propertyName;
            }
            catch(Error $err) {
                $value = null;
            }
            $propertyViolations = $validator->validate($value, $constraints);
            if (count($propertyViolations)) {
                $violations[$propertyName] = $propertyViolations;
            }
        }
        return $violations;
    }
    

    Call it like

    $author = new Author();
    $violations = validateEntity($author);
    

    I only needed it for simple entities so not sure if it works well for more complicated situations.