如何删除具有两个关系的“反向实体”
Posted
技术标签:
【中文标题】如何删除具有两个关系的“反向实体”【英文标题】:How to delete an 'inverse-side entiy' with two relations 【发布时间】:2019-04-06 15:43:20 【问题描述】:销售、库存和目录之间存在双向关系。 销售和库存,应该有一个目录条目。但是这个 目前情况并非总是如此......所以这些关系是“可空的”。
class Sale
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Stock", inversedBy="sales")
*/
private $stock;
public function getCatalog(): ?Catalog
return $this->catalog;
public function setCatalog(?Catalog $catalog): self
$this->catalog = $catalog;
return $this;
class Stock
/**
* @ORM\OneToOne(targetEntity="App\Entity\Catalog", inversedBy="stock")
*/
private $catalog;
public function getCatalog(): ?Catalog
return $this->catalog;
public function setCatalog(?Catalog $catalog): self
$this->catalog = $catalog;
return $this;
class Catalog
/**
* @ORM\OneToMany(targetEntity="App\Entity\Sale", mappedBy="catalog")
*/
private $sales;
/**
* @ORM\OneToOne(targetEntity="App\Entity\Stock", mappedBy="catalog")
*/
private $stock;
public function addSale(Sale $sale): self
if (!$this->sales->contains($sale))
$this->sales[] = $sale;
$sale->setCatalog($this);
return $this;
public function removeSale(Sale $sale): self
if ($this->sales->contains($sale))
$this->sales->removeElement($sale);
// set the owning side to null (unless already changed)
if ($sale->getCatalog() === $this)
$sale->setCatalog(null);
return $this;
public function getStock(): ?Stock
return $this->stock;
public function setStock(?Stock $stock): self
$this->stock = $stock;
// set (or unset) the owning side of the relation if necessary
$newCatalog = $stock === null ? null : $this;
if ($newCatalog !== $stock->getCatalog())
$stock->setCatalog($newCatalog);
return $this;
所有这些都是在 Symfony 中使用 make:entity 自动生成的。整理的时候 目录,也需要删除目录条目。
class CatalogController extends AbstractController
/**
* @Route(
* path = "/catalog-delete/id<[1-9]\d*>",
* name = "catalog_delete",
* methods = "GET"
* )
*/
public function delete(int $id)
// get catalog
$catalog = $this->catalogRepository->find($id);
if (!$catalog)
throw $this->createNotFoundException($this->translator->trans('system.error.notfound') . $id);
// delete
$this->entityManager->remove($catalog);
$this->entityManager->flush();
return $this->redirectToRoute('catalog_list');
到目前为止非常简单。但是我如何删除关联,而不删除 任何股票或销售?我确实遇到了这样的错误(不删除关联)
Cannot delete or update a parent row: a foreign key constraint fails (`symfony`.`sale`, CONSTRAINT `FK_E54BC005DCD6110` FOREIGN KEY (`stock_id`) REFERENCES `stock` (`id`))
或者喜欢
Call to a member function getCatalog() on null
当我在函数 delete() 中尝试时;)
$catalog->setStock(null);
foreach($catalog->getSales() as $sale)
$catalog->getSales()->removeElement($sale); // ????????
我可以使用 DQL 来设置 category_id 销售和库存为空(更新销售/库存 SET category_id = null WHERE category_id = X)。 但我认为这不是常见的“orm 方式”。
对于这种情况,自动生成的函数对我来说有点奇怪 还有这里的学说文档 https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associations.html#removing-associations
我读过,只有拥有方负责关联, 但是我如何获得我的功能 Stock 和 all Sales,如果有的话?
抱歉,问题很长,而且是一个基本主题。
谢谢你和最好的问候
我的问题被标记为重复。主要区别是
我想在我的问题中了解如何实现函数调用以将拥有的实体(两个或多个)设置为空。删除过程。哪个实体,什么样的电话。只添加
@ORM\JoinColumn(name="catalog_id", referencedColumnName="id", onDelete="SET NULL")
(旧答案)不解决问题。
--------- DQL 解决方法 ----------
// Controller
/**
* @Route(
* path = "/catalog-delete/id<[1-9]\d*>",
* name = "catalog_delete",
* methods = "GET"
* )
*/
public function delete(int $id)
// get catalog
$numDeleted = $this->catalogRepository->delete($id);
if (!$numDeleted)
throw $this->createNotFoundException($this->translator->trans('system.error.notfound') . $id);
return $this->redirectToRoute('catalog_list');
// Repository
/**
* Delete with associations
*/
public function delete(int $id): int
$this->getEntityManager()
->createQuery(/** @lang DQL */'
UPDATE App\Entity\Sale s
SET s.catalog = NULL
WHERE s.catalog = :id
')
->setParameter('id', $id)
->execute()
;
$this->getEntityManager()
->createQuery(/** @lang DQL */'
UPDATE App\Entity\Stock s
SET s.catalog = NULL
WHERE s.catalog = :id
')
->setParameter('id', $id)
->execute()
;
$numDeleted = $this->getEntityManager()
->createQuery(/** @lang DQL */'
DELETE FROM App\Entity\Catalog c
WHERE c.id = :id
')
->setParameter('id', $id)
->execute()
;
return $numDeleted;
我最长的帖子;)
【问题讨论】:
Doctrine 2 OneToMany Cascade SET NULL的可能重复 【参考方案1】:解决方案确实是这个简单的设置。它也可以是单向关系。
class Sale
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Stock")
* @ORM\JoinColumn(onDelete="SET NULL")
*/
private $stock;
public function getCatalog(): ?Catalog
return $this->catalog;
public function setCatalog(?Catalog $catalog): self
$this->catalog = $catalog;
return $this;
class Stock
/**
* @ORM\OneToOne(targetEntity="App\Entity\Catalog")
* @ORM\JoinColumn(onDelete="SET NULL")
*/
private $catalog;
public function getCatalog(): ?Catalog
return $this->catalog;
public function setCatalog(?Catalog $catalog): self
$this->catalog = $catalog;
return $this;
class Catalog
然后控制器功能运行良好。昨天我尝试了太多东西......
【讨论】:
以上是关于如何删除具有两个关系的“反向实体”的主要内容,如果未能解决你的问题,请参考以下文章
如何合并具有不同列号的两个表,同时删除具有大量列的表的重复项