Symfony 完整性约束冲突,外键约束失败

Symfony 完整性约束冲突,外键约束失败,symfony,doctrine-orm,foreign-keys,constraints,entity-relationship,Symfony,Doctrine Orm,Foreign Keys,Constraints,Entity Relationship,我有3个实体:发票、发票项服务、资产 首先,我创建了一个Invoice和一个InvoiceItemService,并在InvoiceItemService端通过一个manytone关系将它们链接在一起(因此InvoiceItemService是所有者端) 然后,我可以从Invoice对象创建一个资产。资产是发票的副本,总额为负数。创建资产时,我也会将发票的InvoiceItemService链接到资产,InvoiceItemService和资产之间存在多通关系 当我删除一张发票时,一切正常,发票

我有3个实体:发票、发票项服务、资产

首先,我创建了一个Invoice和一个InvoiceItemService,并在InvoiceItemService端通过一个manytone关系将它们链接在一起(因此InvoiceItemService是所有者端)

然后,我可以从Invoice对象创建一个资产。资产是发票的副本,总额为负数。创建资产时,我也会将发票的InvoiceItemService链接到资产,InvoiceItemService和资产之间存在多通关系

当我删除一张发票时,一切正常,发票、资产和发票项服务通过cascade={“remove”}选项删除

删除资源时,我只希望删除该资源。但是我得到了外键错误

以下是我的实体:

class Invoice
{
    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\Asset", mappedBy="invoice", cascade={"remove"})
     */
    protected $assets;

    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\InvoiceItemService", mappedBy="invoice", cascade={"persist", "remove"})
     */
    protected $services;
}

class Asset
{
    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Invoice", inversedBy="assets")
     * @ORM\JoinColumn(nullable=false)
     * @Exclude
     */
    protected $invoice;

    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\InvoiceItemService", mappedBy="asset")
     */
    protected $services;
}

class InvoiceItemService extends InvoiceItem
{
    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Invoice", inversedBy="services")
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     * @Type("Evo\BackendBundle\Entity\Invoice")
     * @Exclude
     */
    protected $invoice;

    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Asset", inversedBy="services")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     * @Type("Evo\BackendBundle\Entity\Asset")
     * @Exclude
     */
    protected $asset;
}

正如上面评论中提到的Cerad,您需要自己实现此行为

因为您需要访问实体管理器,所以不能通过对资产实体本身进行简单的生命周期回调来实现这一点。相反,您需要注册一个服务来侦听事件并在该点执行操作

示例实现

app/config.yml

services:
    your.bundle.association.manager:
        class: Your\Bundle\Model\AssociationManager
        tags:
            - { name: doctrine.event_listener, event: preRemove }
然后,服务类本身(未声明-可能有bug)


希望这有帮助。

是否有其他实体可能依赖
资产
获取外键?您的错误可能与您在此处发布的这三者之间的关系完全无关。根据SQL错误,我很确定问题就在这里:
外键约束失败(`evotest`.`sfu发票项服务`,约束`FK_38F5C7765DA1941`外键(`asset_id`)引用`sfu资产`(`id`))
实际上,当删除资产时,我需要一个条令选项将InvoiceItemService中的
asset\u id
设置为NULL。尝试了InvoiceItemService#资产属性中的
@ORM\JoinColumn(nullable=true,onDelete=“SET NULL”)
,但仍然存在错误。删除引用资产的任何InvoiceItemService项目取决于您。D2删除级联不够聪明,无法返回上游进行删除。好的,太好了。关键是要明白我必须手动解除这些关系。我已经在资产移除上设置了一个事件侦听器,所以这是小菜一碟。实际上,我只使用了你的
foreach()
部分,其他的都已经编码好了。日复一日,我发现条令越来越令人惊讶,但我认为我在这里发现了它的一个局限性,似乎条令不能自动处理关系分离。无论如何,谢谢你的回复。也要感谢Cerad+给你们两个一个。
namespace Your\Bundle\Model;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManager;
use Your\Bundle\Entity\Asset;

class AssociationManager
{
  public function preRemove(LifecycleEventArgs $args)
  {
    if ($entity instanceof Asset)
    {
      $this->removeAssetAssociations($asset, $args->getEntityManager());
      return;
    }
  }

  protected function removeAssetAssociations(Asset $asset, EntityManager $em)
  {
    foreach ($asset->getServices() as $invoiceItemService)
    {
      $invoiceItemService->asset = null;
      $em->persist($invoiceItemService);
    }
  }
}