Вопрос касается используемого мной стека технологий:
- Symfony 4.2.3
- Doctrine ORM 2.6.3
- Sonata Admin 3.45.2
- sqlite3 3.22 (хотя СУБД не должна играть роли)
Допустим, у нас есть две сущности: Category
и Product
, где категория отношения к продукту равна 1: nи продукт в категории n: 1.Это будет выглядеть так:
Category.php
class Category
{
// ...
/**
* @ORM\OneToMany(
* targetEntity="App\Entity\Product",
* mappedBy="category",
* cascade={"persist"}
* )
* @Assert\Valid()
*/
private $products;
// ...
}
Product.php
class Product
{
// ...
/**
* @ORM\ManyToOne(
* targetEntity="App\Entity\Category",
* inversedBy="samplingDocumentations"
* )
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
*/
private $samplingActivity;
// ...
}
Продукт должен быть присвоен категории . Категория может иметь 0 или более Продукты .Если Категория содержит какие-либо Продукты , это НЕ должно быть удалено. Категория может быть удалена, только если ей не присвоены Продукты .
Когда я пытаюсь удалить Категория , которая имеет Продукты в Sonata Admin, удаление предотвращается, как и ожидалось, и генерируется исключение:
PDOException
SQLSTATE [23000]: нарушение ограничения целостности: 19 FOREIGN KEYограничение не удалось
Теперь это ожидается, но не очень приятно для конечного пользователя.Я хотел бы предоставить сообщение и сообщить пользователю, что Категория не может быть удалена, поскольку она по-прежнему содержит Продукты .
В Sonata Admin я использую обходной путьписать CategoryAdminController
и реализовывать хук preDelete
:
public function preDelete(Request $request, $object)
{
if ($object->getProducts()->isEmpty()) {
return null;
}
$count = $object->getProducts()->count();
$objectName = $this->admin->toString($object);
$this->addFlash(
'sonata_flash_error',
sprintf(
'The category "%s" can not be deleted because it contains %s product(s).',
$objectName,
$count
)
);
return $this->redirectTo($object);
}
Однако это не так, потому что я должен переопределить его за пределами администратора.
Что лучшепрактиковаться, чтобы справиться с этим?Могу ли я реализовать некоторую проверку в сущности?Или, может быть, слушатели событий Doctrine - это то, что нужно?