Sequentially
This constraint allows you to apply a set of rules that should be validated step-by-step, allowing to interrupt the validation once the first violation is raised.
As an alternative in situations Sequentially
cannot solve, you may consider
using GroupSequence which allows more control.
Applies to | property or method |
Class | Sequentially |
Validator | SequentiallyValidator |
Basic Usage
Suppose that you have a Place
object with an $address
property which
must match the following requirements:
- it's a non-blank string
- of at least 10 chars long
- with a specific format
- and geolocalizable using an external service
In such situations, you may encounter three issues:
- the
Length
orRegex
constraints may fail hard with a UnexpectedValueException exception if the actual value is not a string, as enforced byType
. - you may end with multiple error messages for the same property.
- you may perform a useless and heavy external call to geolocalize the address, while the format isn't valid.
You can validate each of these constraints sequentially to solve these issues:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// src/Localization/Place.php
namespace App\Localization;
use App\Validator\Constraints as AcmeAssert;
use Symfony\Component\Validator\Constraints as Assert;
class Place
{
#[Assert\Sequentially([
new Assert\NotNull,
new Assert\Type('string'),
new Assert\Length(min: 10),
new Assert\Regex(Place::ADDRESS_REGEX),
new AcmeAssert\Geolocalizable,
])]
public string $address;
}
1 2 3 4 5 6 7 8 9 10
# config/validator/validation.yaml
App\Localization\Place:
properties:
address:
- Sequentially:
- NotNull: ~
- Type: string
- Length: { min: 10 }
- Regex: !php/const App\Localization\Place::ADDRESS_REGEX
- App\Validator\Constraints\Geolocalizable: ~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<!-- config/validator/validation.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="App\Localization\Place">
<property name="address">
<constraint name="Sequentially">
<constraint name="NotNull"/>
<constraint name="Type">string</constraint>
<constraint name="Length">
<option name="min">10</option>
</constraint>
<constraint name="Regex">
<option name="pattern">/address-regex/</option>
</constraint>
<constraint name="App\Validator\Constraints\Geolocalizable"/>
</constraint>
</property>
</class>
</constraint-mapping>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// src/Localization/Place.php
namespace App\Localization;
use App\Validator\Constraints as AcmeAssert;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
class Place
{
public static function loadValidatorMetadata(ClassMetadata $metadata): void
{
$metadata->addPropertyConstraint('address', new Assert\Sequentially([
new Assert\NotNull(),
new Assert\Type('string'),
new Assert\Length(['min' => 10]),
new Assert\Regex(self::ADDRESS_REGEX),
new AcmeAssert\Geolocalizable(),
]));
}
}
Options
constraints
type: array
[default option]
This required option is the array of validation constraints that you want to apply sequentially.
groups
type: array
| string
default: null
It defines the validation group or groups of this constraint. Read more about validation groups.
payload
type: mixed
default: null
This option can be used to attach arbitrary domain-specific data to a constraint. The configured payload is not used by the Validator component, but its processing is completely up to you.
For example, you may want to use several error levels to present failed constraints differently in the front-end depending on the severity of the error.