Create Reusable Set of Constraints in Symfony 7

Create Reusable Set of Constraints in Symfony 7

In some Symfony applications, it is common to use the same set of constraints in different places. This tutorial explains how to create a reusable set of constraints in Symfony 7 application.

Symfony provides the Compound constraint that defines an abstract getConstraints method. A class that extends Compound constraint should implement the getConstraints method and return a set of constraints.

src/Validator/Constraints/UsernameRequirements.php

<?php

namespace App\Validator\Constraints;

use Attribute;
use Symfony\Component\Validator\Constraints\Compound;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;

#[Attribute]
class UsernameRequirements extends Compound
{
    protected function getConstraints(array $options): array
    {
        return [
            new NotBlank(),
            new Length(['min' => 5]),
        ];
    }
}

Now custom constraint can be used as usual and reused in many places.

src/Entity/User.php

<?php

namespace App\Entity;

use App\Validator\Constraints as AppAssert;

class User
{
    #[AppAssert\UsernameRequirements]
    private string $username;

    public function getUsername(): string { return $this->username; }
    public function setUsername(string $username): void { $this->username = $username; }
}

For testing purpose, in the controller we created an instance of the User class and set a short username. We validate the instance and return a response with errors.

src/Controller/TestController.php

<?php

namespace App\Controller;

use App\Entity\User;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class TestController
{
    #[Route('/')]
    public function index(ValidatorInterface $validator): Response
    {
        $user = new User();
        $user->setUsername('foo');

        $errors = $validator->validate($user);
        if (count($errors) > 0) {
            return new Response((string) $errors); // Output: value is too short
        }

        return new Response('Valid');
    }
}

Leave a Comment

Cancel reply

Your email address will not be published.