Closed
Description
Description
Creates a new composite constraint to validate a composition of constraints. The minumum and maximum validated should be set optionnaly.
Example
For example, there are two use case that could be easily answered with such a composition.
- When properties are exclusive to each other
/**
* @Assert\Compose(
* constraints={
* @Assert\Expression("value.bar !== null"),
* @Assert\Expression("value.baz !== null"),
* },
* min=1,
* max=1,
* minMessage="One of $bar or $baz should be set.",
* maxMessage="Only one of $bar or $baz should be set.",
* )
*/
class Foo {
public $bar;
public $baz;
}
- Password security rules
Often there are security rules to enforce for a new password. Those are limited set, and not all of the rules are mandatory for a valid password. For example, we could have the rules with the following statement:
- at least 8 characters long
- at least 3 of those:
- contains 1 lower case character
- contains 1 upper case character
- contains 1 digit
- contains 1 special character
It is an issue to enforce that a password is complex enough in the current state. Allowing to compose constraints enables simpler code:
class User {
/**
* @Assert\Length(min=8)
* @Assert\Compose(
* constraints={
* @Assert\Regex("/[a-z]/"),
* @Assert\Regex("/[A-Z]/"),
* @Assert\Regex("/\d/"),
* @Assert\Regex("/[,;:.!?]/"),
* },
* min=3,
* minMessage="The password must contains at least one of those 3 character: ...",
* )
*/
public string $password;
}
Basic code
To me, a Compose annotation could look like this:
/**
* @Annotation
* @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
*/
class Compose extends Composite
{
/**
* @var string $minMessage
*/
public string $minMessage = 'compose.min';
/**
* @var string $maxMessage
*/
public string $maxMessage = 'compose.max';
/**
* @var Constraint[] $constraints
*/
public array $constraints = [];
/**
* @var int $min
*/
public int $min = 0;
/**
* @var int|null $max
*/
public ?int $max = null;
public function getDefaultOption()
{
return $this->getCompositeOption();
}
public function getTargets()
{
return [
static::CLASS_CONSTRAINT,
static::PROPERTY_CONSTRAINT,
];
}
protected function getCompositeOption()
{
return 'constraints';
}
}