Example of symfony/validator integration in SlimPHP

Hi! Does anyone have an example of how to integrate symfony/validator into SlimPHP using DTO classes?

Hi! As far as I know the Symfony validator only supports arrays for validation.

Here is a simple example:


use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Exception\ValidationFailedException;
use Symfony\Component\Validator\Validation;

$array = [
    'title' => 'Test',
    'count' => 0,
    'demo' => ['one', 'two', 'three'],
    'box' => true,
];

$validator = Validation::createValidator();

$constraints = new Assert\Collection(
    [
        'title' => new Assert\Length(['min' => 6]),
        'count' => new Assert\Type('integer'),
        'demo' => new Assert\Type('array'),
        'box' => new Assert\Type('boolean'),
    ]
);

$violations = $validator->validate($array, $constraints);

if ($violations->count()) {
    throw new ValidationFailedException('Please check your input', $violations);
}

If you try to pass an object it will not work:

class ExampleDto
{
    public string $title;
    public int $count;
    public array $demo;
    public bool $box;
}

$dto = new ExampleDto();
$dto->title = 'Test';
$dto->demo = ['one', 'two', 'three'];
$dto->box = true;
$dto->count = 1;

// ...

// Exception: This value should be of type array|(Traversable&ArrayAccess).
$violations = $validator->validate($dto, $constraints); 
1 Like

Hi! As far as I know the Symfony validator only supports arrays for validation.

Actually it is not true.

Consider your validation middleware:

use Symfony\Component\Validator\Validation;

        $validator = Validation::createValidatorBuilder()
            ->addMethodMapping('loadValidatorMetadata')
            ->getValidator();
        $errors = $validator->validate($dto);

And your dto:

use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class Dto
{
    private ?int $userId = null;

    public function getUserId(): ?int
    {
        return $this->userId;
    }

    public function setUserId(?int $userId): void
    {
        $this->userId = $userId;
    }

    /**
     * @return array<int, mixed>
     */
    protected static function constraintsUserId(): array
    {
        return [
            new Constraints\Type('int'),
        ];
    }    
    /**
     * @var string[] $fieldsByModes
     */
    protected static array $fieldsByModes = [
        'userId',
    ];

    public static function loadValidatorMetadata(ClassMetadata $metadata): void
    {
        foreach (self::$fieldsByModesas as $field) {
            $metadata->addPropertyConstraints($field, self::{'constraints' . ucfirst($field)}());
        }
    }
}

Should work like a charm.

1 Like