Исключение ForeignKeyConstraintViolationException
Исключение ForeignKeyConstraintViolationException
наследуется от ConstraintViolationException и
выбрасывается Doctrine при попытке вставить, обновить
или удалить запись, которая нарушает ограничение
внешнего ключа. Это происходит, когда операция
ссылается на несуществующую запись в связанной
таблице или когда удаляется запись, на которую
ссылаются другие строки. Исключение содержит
свойства errorInfo с деталями ошибки СУБД
и наследует методы getMessage и
getTrace.
Синтаксис
use DoctrineDBALExceptionForeignKeyConstraintViolationException;
throw new ForeignKeyConstraintViolationException(
$message,
$previous,
$errorInfo
);
Пример
Давайте рассмотрим сущность Comment,
которая ссылается на Article через
внешний ключ article_id:
<?php
namespace AppEntity;
use AppRepositoryCommentRepository;
use DoctrineORMMapping as ORM;
#[ORMEntity(repositoryClass: CommentRepository::class)]
class Comment
{
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn]
private ?int $id = null;
#[ORMColumn(type: 'text')]
private ?string $text = null;
#[ORMManyToOne(targetEntity: Article::class)]
#[ORMJoinColumn(nullable: false)]
private ?Article $article = null;
public function getId(): ?int
{
return $this->id;
}
public function setText(string $text): static
{
$this->text = $text;
return $this;
}
public function setArticle(?Article $article): static
{
$this->article = $article;
return $this;
}
}
?>
Теперь попробуем сохранить комментарий без связанной
статьи - внешний ключ равен null:
<?php
namespace AppController;
use AppEntityComment;
use DoctrineORMEntityManagerInterface;
use DoctrineDBALExceptionForeignKeyConstraintViolationException;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
class CommentController extends AbstractController
{
public function save(EntityManagerInterface $em): Response
{
$comment = new Comment();
$comment->setText('article');
$comment->setArticle(null);
try {
$em->persist($comment);
$em->flush();
} catch (ForeignKeyConstraintViolationException $e) {
return new Response($e->getMessage());
}
return new Response('saved');
}
}
?>
Результат выполнения кода:
"An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails"
Пример
Второй частый случай - удаление статьи, на которую ссылаются комментарии:
<?php
namespace AppController;
use AppEntityArticle;
use DoctrineORMEntityManagerInterface;
use DoctrineDBALExceptionForeignKeyConstraintViolationException;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
class ArticleController extends AbstractController
{
public function remove(int $id, EntityManagerInterface $em): Response
{
$article = $em->getRepository(Article::class)->find($id);
try {
$em->remove($article);
$em->flush();
} catch (ForeignKeyConstraintViolationException $e) {
return new Response($e->getMessage());
}
return new Response('deleted');
}
}
?>
Результат выполнения кода:
"An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails"
Чтобы избежать исключения, нужно сначала удалить
связанные комментарии либо настроить каскадное
удаление через #[ORMJoinColumn(onDelete: 'CASCADE')].
Смотрите также
-
исключение
UniqueConstraintViolationException,
которое возникает при нарушении уникальности поля -
исключение
EntityNotFoundException,
которое выбрасывается при отсутствии сущности -
исключение
DBALException,
базовое исключение уровня DBAL -
метод
getMessage,
который возвращает текст сообщения об ошибке