外键约束不适用于 Doctrine/Symfony 和 SQLite

问题描述 投票:0回答:5

我正在使用 Doctrine 2.4.2、Symfony 2.4 和 SQLite 3.8.3。

我定义了两个实体:

Category:
    type: entity
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    oneToMany:
        ministries:
            targetEntity: Ministry
            cascade: [persist]
            mappedBy: category

还有

Ministry:
    type: entity
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    manyToOne:
        category:
            targetEntity: Category
            inversedBy: ministries
            joinColumn:
                name: category_id
                nullable: false
                onDelete: CASCADE

但是当我删除一个类别时,尽管约束应该级联,但部门实体不会被删除。我错过了什么?

我需要配置任何东西才能使其正常工作吗?

php sqlite symfony doctrine-orm
5个回答
6
投票

您可能需要确保在删除之前设置

PRAGMA foreign_keys = ON

请注意,这是连接设置,而不是数据库设置。

补充:
使用 Symfony 的事件订阅者,可以在执行任何写入查询之前在 Doctrine 的 preFlush 事件中执行此命令。


1
投票

对于通过 Google 来到这里了解为什么外键在原则中不强制执行的其他人。

自版本 2.4.0-BETA1 以来,dbal SqlitePlatform 中的外键支持已根据此评论恢复/删除。

这导致我在代码库中进行了相当多的错误搜索,只是为了发现该学说本身由于不稳定而删除了该功能。


0
投票

更改为

cascade: ['persist', 'remove']


0
投票

pdo_sqlite 驱动程序默认禁用外键检查。正如这里提到的:

默认情况下禁用外键约束(对于向后 兼容性),因此必须为每个数据库单独启用 联系。 (但是请注意,SQLite 的未来版本可能会 更改以便默认启用外键约束。小心 开发商不会对是否为外资做出任何假设 默认情况下启用键,但会启用或禁用它们 必要的。

您应该在通过 EeventSubscriber 刷新之前启用它:

<?php declare(strict_types=1);

namespace App\EventSubscriber;

use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;

/**
 * Class SqlitePreFlushSubscriber.
 */
final class SqlitePreFlushSubscriber implements EventSubscriberInterface
{
    public function preFlush(PreFlushEventArgs $args): void
    {
        if ('sqlite' !== \strtolower($args->getEntityManager()->getConnection()->getDatabasePlatform()->getName())) {
            return;
        }

        $args->getEntityManager()->getConnection()->exec('PRAGMA foreign_keys = ON;');
    }

    /**
     * @return string[]
     */
    public function getSubscribedEvents(): array
    {
        return [Events::preFlush];
    }
}

0
投票

如果你想在 Symfony 6.3 中始终启用 sqlite 的外键约束,你可以创建以下事件监听器:)

<?php
# src/EventListener/SqlitePreFlush.php

namespace App\EventListener;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;

#[AsDoctrineListener(event: Events::preFlush, priority: 500, connection: 'default')]
class SqlitePreFlush
{
    /**
     * @throws Exception
     */
    public function preFlush(PreFlushEventArgs $args): void
    {
        $connection = $args->getObjectManager()->getConnection();
        if ($connection->getDatabasePlatform() instanceof SqlitePlatform) {
            $connection->executeStatement('PRAGMA foreign_keys = ON;');
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.