Исключение UniqueConstraintViolationException
Исключение UniqueConstraintViolationException относится к группе исключений Doctrine DBAL и выбрасывается при попытке вставить или обновить запись, которая нарушает уникальное ограничение (unique constraint) в базе данных. Класс наследуется от ConstraintViolationException и расширяет DBALException. Обычно возникает, когда в таблицу добавляется дублирующее значение для поля, помеченного как unique. Исключение содержит информацию о таблице, в которой произошло нарушение, и о самом конфликте. Symfony перехватывает это исключение через ErrorListener и преобразует его в HTTP-ответ с кодом 500, если оно не обработано.
Синтаксис
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
throw new UniqueConstraintViolationException($driverException, $query);
Пример
Давайте создадим сущность User с уникальным полем email и попытаемся сохранить две записи с одинаковым адресом:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private int $id;
#[ORM\Column(type: 'string', unique: true)]
#[Assert\NotBlank]
private string $email;
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;
}
}
?>
Теперь создадим контроллер, который попытается вставить две записи с одинаковым email:
<?php
namespace App\Controller;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class UserController extends AbstractController
{
#[Route('/user/create', name: 'user_create')]
public function create(EntityManagerInterface $em): Response
{
$user1 = new User();
$user1->setEmail('abcde@example.com');
$em->persist($user1);
$user2 = new User();
$user2->setEmail('abcde@example.com');
$em->persist($user2);
try {
$em->flush();
} catch (UniqueConstraintViolationException $e) {
return new Response('Unique constraint violation: ' . $e->getMessage());
}
return new Response('Users created');
}
}
?>
Результат выполнения кода:
"Unique constraint violation: An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'abcde@example.com' for key 'UNIQ_EMAIL'"
Пример
Давайте обработаем исключение и вернём понятное сообщение пользователю:
<?php
namespace App\Controller;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class UserController extends AbstractController
{
#[Route('/user/register', name: 'user_register')]
public function register(EntityManagerInterface $em): Response
{
$user = new User();
$user->setEmail('user@example.com');
$em->persist($user);
try {
$em->flush();
} catch (UniqueConstraintViolationException $e) {
return new Response('This email is already registered', Response::HTTP_CONFLICT);
}
return new Response('User registered');
}
}
?>
Результат выполнения кода при повторной регистрации:
"This email is already registered"
Смотрите также
-
исключение
DBALException,
которое является базовым для исключений Doctrine DBAL -
исключение
ForeignKeyConstraintViolationException,
которое возникает при нарушении внешнего ключа -
исключение
ORMInvalidArgumentException,
которое выбрасывается при неверных аргументах ORM -
класс
ErrorListener,
который перехватывает исключения и формирует ответ