New in Symfony 7.2: Compound Constraint Improvements
The Compound constraint allows you to group other constraints into a single
reusable constraint to apply the same validation in different parts of your application.
For example, you can validate your password policy by checking all conditions with
a set of constraints like this:
// src/Validator/MatchPasswordPolicy.php
use SymfonyComponentValidatorConstraints as Assert;
class MatchPasswordPolicy extends AssertCompound
{
protected function getConstraints(array $options): array
{
return [
new AssertNotBlank(allowNull: false),
new AssertLength(min: 8, max: 255),
new AssertNotCompromisedPassword(),
new AssertType(’string‘),
new AssertRegex(‚/[A-Z]+/‘),
// …
];
}
}
Then, in your User entity, you can apply this compound constraint like this:
// src/Entity/User.php
namespace AppEntityUser;
use AppValidatorConstraints as Assert;
class User
{
public string $plainPassword;
// …
}
In Symfony 7.2 we’ve added some features to make working with compound constraints easier.
Easier Compound Constraint Tests
Testing compound constraints used to be unnecessarily complex. That’s why we’re
introducing a new CompoundConstraintTestCase class to simplify those tests.
This is an abstract class that requires defining a single method:
abstract class CompoundConstraintTestCase extends TestCase
{
abstract protected function createCompound(): Compound;
// …
}
Using the same MatchPasswordPolicy compound constraint shown earlier, you
can now write a test for it like this:
// tests/Validator/MatchPasswordPolicyTest.php
use SymfonyComponentValidatorConstraints as Assert;
use SymfonyComponentValidatorTestCompoundConstraintTestCase;
class MatchPasswordPolicyTest extends CompoundConstraintTestCase
{
public function createCompound(): AssertCompound
{
return new MatchPasswordPolicy();
}
/**
* @dataProvider provideInvalidPasswords
*/
public function testInvalid(mixed $password, string $code): void
{
$this->validateValue($password);
$this->assertViolationIsRaisedByCompound($code);
}
public static function provideInvalidPasswords(): Generator
{
yield ‚Blank‘ => [“, AssertNotBlank::IS_BLANK_ERROR];
yield ‚Too short‘ => [‚a‘, AssertLength::TOO_SHORT_ERROR];
yield ‚Not a string‘ => [1, AssertType::INVALID_TYPE_ERROR];
// …
}
public function testValid(): void
{
$this->validateValue(‚VeryStr0ngP4$$wOrD‘);
$this->assertNoViolation();
}
}
Add Groups and Payload Constructor Arguments
A while ago, we added the $groups and $payload arguments to the constructor
of many composite constraints, but we didn’t add them to the compound constraint.
In Symfony 7.2, we’re adding those arguments so you can pass them in the constructor:
class User
{
(
groups: [‚registration‘],
payload: [’severity‘ => ‚error‘],
)
public string $plainPassword;
// …
}
Symfony Blog