使用 StofDoctrineExtensionsBundle 生成 Softdeleteable 查询

Generating Softdeleteable query with StofDoctrineExtensionsBundle

我期待,它应该在我执行 DELETE 查询后更新 deleted_at 字段。它应该在 SELECT 查询的末尾添加 deleted_at is null 条件。但它确实删除了具有愚蠢条件的行。怎么了?

$query = $this->entityManager->createQueryBuilder()
    ->delete("AppBundle:ReportRow", "r")
    ->where("r.date <= :date")
    ->andWhere("r.balance is null")
    ->andWhere("r.name = :name")
    ->setParameters(array("date" => $date->format("Y-m-d"),
                            "name" => $user->getName()))
    ->getQuery();

$output->writeln($query->getSQL());

这是输出:

DELETE FROM report_row 
WHERE (date <= ? AND balance_id IS NULL AND name = ?) 
AND (report_row.deleted_at IS NULL) // really ?? its delete query dude!

这是我的配置

doctrine:
    ...
    orm:
        ...
        filters:
            softdeleteable:
                class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
                enabled: true

stof_doctrine_extensions:
    orm:
        default:
            softdeleteable: true

此问题已提交给开发人员,目前自 2014 年起在 https://github.com/Atlantic18/DoctrineExtensions/issues/1125

待决

解释:

当您使用 QueryBuilder 创建 DELETE 语句时,您绕过了 onFlush 事件侦听器,该侦听器用于防止条目的物理删除,因为您不再使用 $em->remove($entity) 时在实体管理器中工作,而是手动发出 SQL 语句。

结果是 softdeletable 过滤器不再管理您的查询意图,但仍然知道 deleted_at 元数据。


要解决此问题,您必须使用带有 SoftDeleteableWalker 的查询提示,如 documentation

中所述
$query = $this->entityManager->createQueryBuilder()
    ->delete("AppBundle:ReportRow", "r")
    ->where("r.date <= :date")
    ->andWhere("r.balance is null")
    ->andWhere("r.name = :name")
    ->setParameters(array("date" => $date->format("Y-m-d"),
                            "name" => $user->getName()))
    ->getQuery();

$query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            \Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker::class);

$output->writeln($query->getSQL());

结果:

UPDATE report_row 
SET deleted_at = '2017-10-03 15:06:48'
WHERE (date <= ? AND balance_id IS NULL AND name = ?)