Skip to content

[Validator] Advanced Validation Group Provider #18744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions validation/sequence_provider.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,100 @@ provides a sequence of groups to be validated:
}
}

Advanced Validation Group Provider
----------------------------------

In the previous section, you learned how to dynamically determine the
sequence of groups to apply based on the state of your entity. This
approach covers most common scenarios, but for more advanced needs, you
may find it to be insufficient.

For instance, suppose you need to provide the sequence of groups from an
external configuration or service that can change its value dynamically.
Managing the entity initialization and manually setting its dependencies can
be cumbersome, and the implementation might not align with the entity
responsibilities.

To address this, you can now configure the implementation of the
:class:`Symfony\\Component\\Validator\\GroupProviderInterface`
outside of the entity, and even register the group provider as a
service if necessary.

Here's how you can achieve this:

1) **Define a Separate Group Provider Class:** You can create a class that
implements the :class:`Symfony\\Component\\Validator\\GroupProviderInterface`
and handles the dynamic group sequence logic.
2) **Configure the User with the Provider:** Use the ``provider`` option within the
:class:`Symfony\\Component\\Validator\\Constraints\\GroupSequenceProvider`
attribute to link the entity with the provider class.
3) **Autowiring or Manual Tagging:** If autowiring is enabled, your custom provider
will be automatically linked. Otherwise, you can manually tag your service with
``validator.group_provider``.

.. configuration-block::

.. code-block:: php-attributes

// src/Entity/User.php
namespace App\Entity;

// ...
use App\Validator\UserGroupProvider;

#[Assert\GroupSequenceProvider(provider: UserGroupProvider::class)]
class User
{
// ...
}

.. code-block:: yaml

# config/validator/validation.yaml
App\Entity\User:
group_sequence_provider: App\Validator\UserGroupProvider

.. code-block:: xml

<!-- 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\Entity\User">
<group-sequence-provider>
<value>App\Validator\UserGroupProvider</value>
</group-sequence-provider>
<!-- ... -->
</class>
</constraint-mapping>

.. code-block:: php

// src/Entity/User.php
namespace App\Entity;

// ...
use App\Validator\UserGroupProvider;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class User
{
// ...

public static function loadValidatorMetadata(ClassMetadata $metadata): void
{
$metadata->setGroupProvider(UserGroupProvider::class);
$metadata->setGroupSequenceProvider(true);
// ...
}
}

With this approach, you can maintain a clean separation between the entity
structure and the group sequence logic, allowing for more advanced use cases.

How to Sequentially Apply Constraints on a Single Property
----------------------------------------------------------

Expand Down