New in Symfony 7.1: Expanding UniqueEntity Constraint to Any PHP Class
May 14, 2024 • Published by Javier Eguiluz
Symfony 7.1 is backed by:
In Symfony applications, the UniqueEntity constraint validates that some field (or fields) in a Doctrine entity is (are) unique. This is useful for example to prevent a new user to register using an email address that already exists in the system.
In Symfony 7.1, we're improving this constraint to also check uniqueness on any PHP class (e.g. DTOs) and not only on Doctrine entities. Consider the following Doctrine entity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Entity/User.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class User
{
#[ORM\Column(type: 'string')]
public string $id;
#[ORM\Column(type: 'string')]
public string $username;
}
Instead of adding the UniqueEntity
constraint to it, you can now check for
uniqueness in other ways. For example, in a Messenger component message that
creates User
entities, you can now define the following:
1 2 3 4 5 6 7 8 9 10 11 12
namespace App\Message;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(fields: ['username'], entityClass: User::class)]
class HireAnEmployee
{
public function __construct(
private string $username
) {
}
}
Although the HireAnEmployee
class is not a Doctrine entity, this constraint
will effectively check that the given username
value is unique for the User
Doctrine class.
If the names of the unique properties in this class are different from the Doctrine entity property names, you can map them:
1 2 3 4 5 6
#[UniqueEntity(
// 'userIdentifier' is the property name in the PHP class and
// 'username' is the property name in the Doctrine entity
fields: ['userIdentifier' => 'username'],
entityClass: User::class,
)]
When updating an entity, use the identifierFieldNames
option to define the
class properties that are used as the Doctrine entity key (or composite key):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
namespace App\Message;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[UniqueEntity(
fields: ['name'],
entityClass: User::class,
// 'uid' is the property name in the PHP class and 'id' is the name of
// the Doctrine entity property used as the primary key
identifierFieldNames: ['uid' => 'id'],
)]
class UpdateEmployeeProfile
{
public function __construct(
private string $uid,
private string $name,
) {
}
}
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
I'm not sure I understand the last part about "identifierFieldNames". Does this mean the entity targeted by the DTO is not considered when checking for duplicate field values?
@Cédric When we want to edit an entity, we do not want to have a validation error as a result of finding the entity being edited. That is why you need to specify its identifier to exclude it. The values are still validated against other entities. The behavior is exactly the same as in Symfony 7.0.
i am getting Class "doctrine.orm.validator.unique" not found. this is composer.json file "doctrine/dbal": "^4.0", "doctrine/doctrine-bundle": "^2.12", "doctrine/doctrine-fixtures-bundle": "^3.4", "doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/orm": "^3.2", "symfony/doctrine-bridge": "7.1.*",
This was one of the most wanted features, thanks a lot !