diff --git a/reference/constraints.rst b/reference/constraints.rst index f3851bdb97a..9b83eda23ca 100644 --- a/reference/constraints.rst +++ b/reference/constraints.rst @@ -72,6 +72,7 @@ Validation Constraints Reference constraints/Compound constraints/Callback constraints/Expression + constraints/When constraints/All constraints/UserPassword constraints/NotCompromisedPassword diff --git a/reference/constraints/When.rst b/reference/constraints/When.rst new file mode 100644 index 00000000000..79f1cb8ffa2 --- /dev/null +++ b/reference/constraints/When.rst @@ -0,0 +1,288 @@ +When +==== + +.. versionadded:: 6.2 + + The ``When`` constraint was introduced in Symfony 6.2. + +This constraint allows you to apply constraints validation only if the +provided expression returns true. See `Basic Usage`_ for an example. + +========== =================================================================== +Applies to :ref:`class ` + or :ref:`property/method ` +Options - `expression`_ + - `constraints`_ + - `groups`_ + - `payload`_ + - `values`_ +Class :class:`Symfony\\Component\\Validator\\Constraints\\When` +Validator :class:`Symfony\\Component\\Validator\\Constraints\\WhenValidator` +========== =================================================================== + +Basic Usage +----------- + +Imagine you have a class ``Discount`` with ``type`` and ``value`` +properties:: + + // src/Model/Discount.php + namespace App\Model; + + class Discount + { + private ?string $type; + + private ?int $value; + + // ... + + public function getType(): ?string + { + return $this->type; + } + + public function getValue(): ?int + { + return $this->value; + } + } + +To validate the object, you have some requirements: + +A) If ``type`` is ``percent``, then ``value`` must be less than or equal 100; +B) If ``type`` is ``absolute``, then ``value`` can be anything; +C) No matter the value of ``type``, the ``value`` must be greater than 0. + +One way to accomplish this is with the When constraint: + +.. configuration-block:: + + .. code-block:: php-attributes + + // src/Model/Discount.php + namespace App\Model; + + use Symfony\Component\Validator\Constraints as Assert; + + class Discount + { + #[Assert\GreaterThan(0)] + #[Assert\When( + expression: 'this.type == "percent"', + constraints: [ + new Assert\LessThanOrEqual(100, message: 'The value should be between 1 and 100!') + ], + )] + private ?int $value; + + // ... + } + + .. code-block:: yaml + + # config/validator/validation.yaml + App\Model\Discount: + properties: + value: + - GreaterThan: 0 + - When: + expression: "this.type == 'percent'" + constraints: + - LessThanOrEqual: + value: 100 + message: "The value should be between 1 and 100!" + + .. code-block:: xml + + + + + + + 0 + + + + + + + + + .. code-block:: php + + // src/Model/Discount.php + namespace App\Model; + + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\Mapping\ClassMetadata; + + class Discount + { + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('value', new Assert\GreaterThan(0)); + $metadata->addPropertyConstraint('value', new Assert\When([ + 'expression' => 'this.type == "percent"', + 'constraints' => [ + new Assert\LessThanOrEqual([ + 'value' => 100, + 'message' => 'The value should be between 1 and 100!', + ]), + ], + ])); + } + + // ... + } + +The `expression`_ option is the expression that must return true in order +to trigger the validation of the attached constraints. To learn more about +the expression language syntax, see :doc:`/components/expression_language/syntax`. + +For more information about the expression and what variables are available +to you, see the `expression`_ option details below. + +Options +------- + +``expression`` +~~~~~~~~~~~~~~ + +**type**: ``string`` + +The condition written with the expression language syntax that will be evaluated. +If the expression evaluates to a falsey value (i.e. using ``==``, not ``===``), +validation of constraints won't be triggered. + +To learn more about the expression language syntax, see +:doc:`/components/expression_language/syntax`. + +Depending on how you use the constraint, you have access to 1 or 2 variables +in your expression: + +``this`` + The object being validated (e.g. an instance of Discount). +``value`` + The value of the property being validated (only available when + the constraint is applied to a property). + +The ``value`` variable can be used when you want to execute more complex +validation based on its value: + +.. configuration-block:: + + .. code-block:: php-attributes + + // src/Model/Discount.php + namespace App\Model; + + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\Context\ExecutionContextInterface; + + class Discount + { + #[Assert\When( + expression: 'value == "percent"', + constraints: [new Assert\Callback('doComplexValidation')], + )] + private ?string $type; + // ... + + public function doComplexValidation(ExecutionContextInterface $context, $payload) + { + // ... + } + } + + .. code-block:: yaml + + # config/validator/validation.yaml + App\Model\Discount: + properties: + type: + - When: + expression: "value == 'percent'" + constraints: + - Callback: doComplexValidation + + .. code-block:: xml + + + + + + + + + + + + + + + .. code-block:: php + + // src/Model/Discount.php + namespace App\Model; + + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\Mapping\ClassMetadata; + + class Discount + { + // ... + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('type', new Assert\When([ + 'expression' => 'value == "percent"', + 'constraints' => [ + new Assert\Callback('doComplexValidation'), + ], + ])); + } + + public function doComplexValidation(ExecutionContextInterface $context, $payload) + { + // ... + } + } + +You can also pass custom variables using the `values`_ option. + +``constraints`` +~~~~~~~~~~~~~~~ + +**type**: ``array`` + +The constraints that are applied if the expression returns true. + +.. include:: /reference/constraints/_groups-option.rst.inc + +.. include:: /reference/constraints/_payload-option.rst.inc + +``values`` +~~~~~~~~~~ + +**type**: ``array`` **default**: ``[]`` + +The values of the custom variables used in the expression. Values can be of any +type (numeric, boolean, strings, null, etc.)