A Custom Validator
A Custom Validator
~16 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
The built-in constraints don't ALWAYS suffice – a CUSTOM validator here checks whether a project's name ALREADY exists.
Creating the constraint class
docker compose exec php bin/console make:validator UniqueProjectName<?php
declare(strict_types=1);
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
final class UniqueProjectName extends Constraint
{
public string $message = 'A project named "{{ value }}" already exists.';
}Implementing the validator
<?php
declare(strict_types=1);
namespace App\Validator;
use App\Repository\ProjectRepository;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
final class UniqueProjectNameValidator extends ConstraintValidator
{
public function __construct(
private readonly ProjectRepository $projectRepository,
) {
}
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof UniqueProjectName) {
return;
}
if (null === $value || '' === $value) {
return;
}
$existing = $this->projectRepository->findOneBy(['name' => $value]);
if (null !== $existing) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $value)
->addViolation();
}
}
}EXACTLY the same Constraint/ConstraintValidator pair principle as in the Symfony course (chapter 26) – dependency injection works NORMALLY inside the validator, ProjectRepository gets injected AUTOMATICALLY.
Applying the validator
use App\Validator\UniqueProjectName;
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[UniqueProjectName]
#[Groups(['project:read', 'project:write'])]
private string $name = '';Testing the behavior
curl -k -X POST https://localhost/api/projects \
-H 'Content-Type: application/json' \
-d '{"name": "Website Relaunch"}'{
"violations": [
{"propertyPath": "name", "message": "A project named \"Website Relaunch\" already exists."}
]
}Tipp: Symfony ALSO offers a ready-made #[UniqueEntity] constraint for EXACTLY this case – this chapter deliberately shows the MANUAL approach, since it demonstrates HOW arbitrary CUSTOM business rules (not just uniqueness) can be implemented as a validator.