默认清除器由默认清除器工厂创建。至少在 MySQL 上,使用默认的清除器清除复杂的关系图很麻烦(请参阅尝试重新加载装置时出现问题 https://stackoverflow.com/questions/7405356/issue-when-trying-to-reload-the-fixtures),您发现的解决方案是在删除过程中禁用外键检查。
默认情况下,解决方案分为三个部分来执行此操作,而无需在每个控制台命令上显式指定清除程序。
首先创建purger,它简单地继承了ORMPurger
为了不丢失任何功能(特别是排除项):
<?php
namespace App\Doctrine\Fixtures;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
class MySQLPurger extends ORMPurger
{
/**
* {@inheritDoc}
*/
public function __construct(private readonly EntityManagerInterface $entityManager, array $excluded = [])
{
parent::__construct($this->entityManager, $excluded);
}
/**
* Purges the MySQL database with temporarily disabled foreign key checks.
*
* {@inheritDoc}
*/
public function purge(): void
{
$connection = $this->entityManager->getConnection();
try {
$connection->executeStatement('SET FOREIGN_KEY_CHECKS = 0');
parent::purge();
} finally {
$connection->executeStatement('SET FOREIGN_KEY_CHECKS = 1');
}
}
}
然后创建创建净化器的工厂:
<?php
namespace App\Doctrine\Fixtures;
use Doctrine\Bundle\FixturesBundle\Purger\PurgerFactory;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\Common\DataFixtures\Purger\PurgerInterface;
use Doctrine\ORM\EntityManagerInterface;
class MySQLPurgerFactory implements PurgerFactory
{
/**
* Adapted from {@see \Doctrine\Bundle\FixturesBundle\Purger\ORMPurgerFactory} to return a MySQL-specific {@see PurgerInterface}.
*
* {@inheritDoc}
*/
public function createForEntityManager(
?string $emName,
EntityManagerInterface $em,
array $excluded = [],
bool $purgeWithTruncate = false
): PurgerInterface {
$purger = new MySQLPurger($em, $excluded);
$purger->setPurgeMode($purgeWithTruncate ? ORMPurger::PURGE_MODE_TRUNCATE : ORMPurger::PURGE_MODE_DELETE);
return $purger;
}
}
最后,覆盖服务配置中的默认清除器工厂:
services:
# Override the default purger factory with the MySQLPurgerFactory, which skips foreign key checks.
doctrine.fixtures.purger.orm_purger_factory:
class: App\Doctrine\Fixtures\MySQLPurgerFactory
tags:
- { name: doctrine.fixtures.purger_factory, alias: default }