Skip to content

Commit 23ab4b6

Browse files
committed
[DoctrineBridge][Validator] Allow validating every class against unique entity constraint
1 parent 9804422 commit 23ab4b6

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

reference/constraints/UniqueEntity.rst

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Validates that a particular field (or fields) in a Doctrine entity is (are)
55
unique. This is commonly used, for example, to prevent a new user to register
66
using an email address that already exists in the system.
77

8+
.. versionadded:: 7.1
9+
10+
Any class instance (like DTO) field (or fields) validation against entities persisted in the database was introduced in Symfony 7.1.
11+
812
.. seealso::
913

1014
If you want to validate that all the elements of the collection are unique
@@ -162,6 +166,7 @@ the current class instance. However, in some cases, such as when using Doctrine
162166
inheritance mapping, you need to execute the query in a different repository.
163167
Use this option to define the fully-qualified class name (FQCN) of the Doctrine
164168
entity associated with the repository you want to use.
169+
Another case is when the object being validated is not an entity.
165170

166171
``errorPath``
167172
~~~~~~~~~~~~~
@@ -274,6 +279,125 @@ each with a single field.
274279

275280
.. include:: /reference/constraints/_groups-option.rst.inc
276281

282+
If object being validated field name(s) do not match the one(s) from the entity,
283+
use key-value mapping; Where ``key`` is the name of the field in the object being
284+
validated and ``value`` is the name of the field in the entity.
285+
Field name(s) mapping only applies when the object being validated is not an entity.
286+
287+
``identifierFieldNames``
288+
~~~~~~~~~~~~~~~~~~~~
289+
290+
**type**: ``array`` | ``string`` [:ref:`default option <validation-default-option>`]
291+
292+
Use it only when the object being validated is not an entity and you need to update an
293+
entity with it.
294+
This option is the identifier field name that is the ``primary key`` or the identifier
295+
field names that are ``composite keys`` in the entity class set by the `entityClass`_
296+
option.
297+
If set, it won’t trigger a uniqueness constraint violation when the only not unique
298+
entity identifier(s) value(s) will be matching corresponding value(s) from the
299+
object being validated.
300+
If object being validated field name(s) do not match the one(s) from the entity,
301+
use key-value mapping; Where ``key`` is the name of the field in the object being
302+
validated and ``value`` is the name of the field in the entity.
303+
304+
Consider this example:
305+
306+
.. configuration-block::
307+
308+
.. code-block:: php-attributes
309+
310+
// src/Entity/User.php
311+
namespace App\Entity;
312+
313+
use Doctrine\ORM\Mapping as ORM;
314+
315+
#[ORM\Entity]
316+
class User
317+
{
318+
#[ORM\Column(type: 'string')]
319+
public string $id;
320+
321+
#[ORM\Column(type: 'string')]
322+
public string $username;
323+
}
324+
325+
// src/Message/UpdateEmployeeProfile.php
326+
namespace App\Message;
327+
328+
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
329+
330+
#[UniqueEntity(
331+
fields: ['name' => 'username'],
332+
entityClass: 'App\Entity\User',
333+
identifierFieldNames: ['uid' => 'id'],
334+
)]
335+
class UpdateEmployeeProfile
336+
{
337+
public function __construct(public string $uid, public string $name)
338+
{
339+
}
340+
}
341+
342+
.. code-block:: yaml
343+
344+
# config/validator/validation.yaml
345+
App\Message\UpdateEmployeeProfile:
346+
constraints:
347+
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
348+
fields: {name: username}
349+
entityClass: 'App\Entity\User'
350+
identifierFieldNames: {uid: id}
351+
352+
.. code-block:: xml
353+
354+
<!-- config/validator/validation.xml -->
355+
<?xml version="1.0" encoding="UTF-8" ?>
356+
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
357+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
358+
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
359+
360+
<class name="App\Message\UpdateEmployeeProfile">
361+
<constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
362+
<option name="fields">
363+
<value key="name" >username</value>
364+
</option>
365+
<option name="entityClass">App\Entity\User</option>
366+
<option name="identifierFieldNames">
367+
<value key="uid" >id</value>
368+
</option>
369+
</constraint>
370+
</class>
371+
372+
</constraint-mapping>
373+
374+
.. code-block:: php
375+
376+
// src/Message/UpdateEmployeeProfile.php
377+
namespace App\Message;
378+
379+
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
380+
use Symfony\Component\Validator\Mapping\ClassMetadata;
381+
382+
class UpdateEmployeeProfile
383+
{
384+
public $uid;
385+
public $name;
386+
387+
public static function loadValidatorMetadata(ClassMetadata $metadata)
388+
{
389+
$metadata->addConstraint(new UniqueEntity([
390+
'fields' => ['name' => 'username'],
391+
'entityClass' => 'App\Entity\User',
392+
'identifierFieldNames' => ['uid' => 'id'],
393+
]));
394+
}
395+
}
396+
397+
.. versionadded:: 7.1
398+
399+
The option was introduced in Symfony 7.1.
400+
277401
``ignoreNull``
278402
~~~~~~~~~~~~~~
279403

0 commit comments

Comments
 (0)