Application input often crosses forms, controllers, console commands, and services before it reaches storage or outbound systems. In Symfony, validator constraints give those layers one shared way to reject blank, malformed, or out-of-range values before the application acts on them.
Symfony Validator reads constraints from PHP attributes, YAML, XML, PHP metadata, and form field options. Putting constraints on the object that carries submitted data keeps forms, manual validator calls, tests, and API handlers aligned around the same rules.
A small ContactRequest model is enough to verify the rule path without adding a database table or controller. The Email constraint checks format, while NotBlank keeps the field required; using both avoids treating an empty optional value as an acceptable contact address.
Related: How to create a Symfony form
Related: How to create a Symfony registration form
Steps to add Symfony validation rules:
- Work from the Symfony project root.
Use the directory that contains composer.json and bin/console. If the application does not already include the validator component, add it with composer require symfony/validator before adding constraints.
- Create a namespace for the data object when the project does not already have one.
$ mkdir -p src/Model
Use an existing entity, form model, DTO, or command input class when the application already has the object that should receive the rule.
- Save ContactRequest.php under src/Model with validation attributes on each property.
<?php namespace App\Model; use Symfony\Component\Validator\Constraints\{ Email, Length, NotBlank, }; final class ContactRequest { #[NotBlank( message: 'Enter an email address.', )] #[Email( message: 'Enter a valid email address.', )] public ?string $email = null; #[NotBlank( message: 'Enter a message.', )] #[Length( min: 10, max: 500, minMessage: 'Message is too short.', maxMessage: 'Message is too long.', )] public ?string $message = null; }
NotBlank makes the field required. Email and Length allow blank values when they are used alone, so pair them with NotBlank when the field must be filled in.
- Confirm that Symfony reads the constraints from the class.
$ php bin/console debug:validator \ 'App\Model\ContactRequest'
The output should list email with NotBlank and Email, plus message with NotBlank and Length. A missing class, typo in the namespace, or missing validator package appears here before form handling or controller code gets involved.
- Save ContactRequestTest.php under tests/Validator with rejected and accepted values.
<?php namespace App\Tests\Validator; use App\Model\ContactRequest; use Symfony\Bundle\FrameworkBundle\Test\{ KernelTestCase, }; final class ContactRequestTest extends KernelTestCase { public function testInvalidRequestFails(): void { self::bootKernel(); $request = new ContactRequest(); $request->email = 'not-an-email'; $request->message = 'short'; $validator = self::getContainer()->get('validator'); $violations = $validator->validate($request); $messages = []; foreach ($violations as $violation) { $messages[] = sprintf( '%s: %s', $violation->getPropertyPath(), $violation->getMessage(), ); } self::assertContains( 'email: Enter a valid email address.', $messages, ); self::assertContains( 'message: Message is too short.', $messages, ); } public function testValidRequestPasses(): void { self::bootKernel(); $request = new ContactRequest(); $request->email = 'reader@example.com'; $request->message = 'Send the notes.'; $validator = self::getContainer()->get('validator'); $violations = $validator->validate($request); self::assertCount(0, $violations); } }
Keep the test close to the rule. The first method proves the invalid values produce the expected messages, and the second method prevents the rule from blocking a normal contact request.
- Run the validation test.
$ php bin/phpunit tests/Validator --testdox PHPUnit 13.2.1 by Sebastian Bergmann and contributors. ##### snipped ##### Contact Request (App\Tests\Validator\ContactRequest) ✔ Invalid request fails ✔ Valid request passes OK (2 tests, 3 assertions)
Run the full application test suite after adapting the rule to a real entity or form model.
Related: How to run PHPUnit tests in Symfony
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.