Атрибут UniqueConstraint
Атрибут UniqueConstraint вешается на класс
сущности и гарантирует, что комбинация значений
указанных полей будет уникальной в таблице базы
данных. Первым параметром передаётся массив имён
полей, которые должны быть уникальными в
совокупности. Дополнительно можно указать имя
ограничения и опции для конкретной СУБД.
Синтаксис
#[UniqueConstraint(name: name, fields: [field1, field2])]
Пример
Давайте создадим сущность User с уникальным
ограничением на поле email:
<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
#[ORMEntity]
#[ORMTable(name: 'users')]
#[ORMUniqueConstraint(name: 'uniq_email', fields: ['email'])]
class User
{
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn(type: 'integer')]
private ?int $id = null;
#[ORMColumn(type: 'string', length: 255)]
private string $email;
#[ORMColumn(type: 'string', length: 255)]
private string $name;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
?>
После применения миграции в таблице users
появится уникальный индекс uniq_email на
колонке email. Повторная вставка записи с
тем же адресом вызовет ошибку целостности.
Пример
Давайте зададим составное уникальное ограничение
на пару полей name и email:
<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
#[ORMEntity]
#[ORMTable(name: 'users')]
#[ORMUniqueConstraint(name: 'uniq_name_email', fields: ['name', 'email'])]
class User
{
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn(type: 'integer')]
private ?int $id = null;
#[ORMColumn(type: 'string', length: 255)]
private string $email;
#[ORMColumn(type: 'string', length: 255)]
private string $name;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
?>
Теперь уникальной должна быть именно пара значений.
Две записи с одинаковым name, но разными
email сохранятся успешно. А вот полные
дубликаты пары вызовут ошибку.
Пример
Давайте посмотрим, как выглядит определение ограничения через атрибут на классе-сущности с полями разных типов:
<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
#[ORMEntity]
#[ORMTable(name: 'articles')]
#[ORMUniqueConstraint(name: 'uniq_slug_locale', fields: ['slug', 'locale'])]
class Article
{
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn(type: 'integer')]
private ?int $id = null;
#[ORMColumn(type: 'string', length: 255)]
private string $slug;
#[ORMColumn(type: 'string', length: 5)]
private string $locale;
#[ORMColumn(type: 'text')]
private string $text;
#[ORMColumn(type: 'boolean')]
private bool $published = false;
public function getId(): ?int
{
return $this->id;
}
public function getSlug(): string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getLocale(): string
{
return $this->locale;
}
public function setLocale(string $locale): self
{
$this->locale = $locale;
return $this;
}
public function getText(): string
{
return $this->text;
}
public function setText(string $text): self
{
$this->text = $text;
return $this;
}
public function isPublished(): bool
{
return $this->published;
}
public function setPublished(bool $published): self
{
$this->published = $published;
return $this;
}
}
?>
Ограничение uniq_slug_locale не даст создать
две статьи с одинаковым slug в рамках одного
locale.
Пример
Давайте выведем список уникальных ограничений сущности через метаданные Doctrine:
<?php
namespace AppController;
use AppEntityArticle;
use DoctrineORMEntityManagerInterface;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
class ArticleController extends AbstractController
{
public function index(EntityManagerInterface $em): Response
{
$meta = $em->getClassMetadata(Article::class);
$res = [];
foreach ($meta->table['uniqueConstraints'] as $name => $constraint) {
$res[] = $name . ': ' . implode(', ', $constraint['columns']);
}
return new Response(implode(' | ', $res));
}
}
?>
Результат выполнения кода:
"uniq_slug_locale: slug, locale"