Doctrine QueryBuilder 使用联接删除

2022-08-30 21:04:01

我正在尝试使用 Doctrine QueryBuilder 来执行以下 SQL 查询:

DELETE php FROM product_hole_pattern php
INNER JOIN hole_pattern hp ON php.hole_pattern_id = hp.id
INNER JOIN hole_pattern_type hpt ON hp.hole_pattern_type_id = hpt.id
WHERE php.product_id = 4 AND hpt.slug='universal';

我有这个

$qb = $this->entityManager->createQueryBuilder();
$query = $qb->delete('\SANUS\Entity\ProductHolePattern', 'php')
  ->innerJoin('php.holePattern', 'hp')
  ->innerJoin('hp.holePatternType', 'hpt')
  ->where('hpt.slug = :slug AND php.product=:product')
  ->setParameter('slug','universal')
  ->setParameter('product',$this->id)
  ->getQuery();

但我得到:

[Semantical Error] line 0, col 50 near 'hpt.slug = :slug': Error: 'hpt' is not defined.

错误消息附带的 DQL 是:

DELETE \SANUS\Entity\ProductHolePattern php 
WHERE hpt.slug = :slug AND php.product=:product

因此,连接似乎被完全省略了。


答案 1

最好使用 IN 条件运行查询,而不是迭代。

$ids = $this->createQueryBuilder('product')
->join('..your joins..')
->where('..your wheres..')
->select('product.id')
->getQuery()->getResult();

$this->createQueryBuilder('product')
    ->where('product.id in (:ids)')
    ->setParameter('ids', $ids)
    ->delete()
    ->getQuery()
    ->execute();
  • 优点:运行速度更快,无需迭代
  • 缺点:您无法挂钩到预删除

至于激烈的“放在哪里”的争论,如果你愿意,敢把它放在控制器里。这完全取决于你。但是,如果您将代码放在专用的 doctrine 存储库类中,它将来可能对您更有用。它应该非常容易做到,并使其易于更改/维护。


答案 2

看起来 DQL 不支持这种删除语句。Doctrine 文档中的 BNF 表明,必须采用以下形式delete_statement

delete_clause [where_clause]

其中定义为:delete_clause

"DELETE" "FROM" abstract_schema_name [["AS"] identification_variable]

因此,我可以提供架构和 where 子句,但没有连接。


推荐