好的,这就是问题所在。
我有一个名为 HelpDocuments 的实体和一个名为 LogEntry 的实体。
用户可以关闭帮助文档。发生这种情况时,我会创建一个具有以下属性的 LogEntry:
- 事件 - 例如:helpDocument.dismiss
 - entity_id - 例如:11
 - entityDiscriminator - 例如:HelpDocument
 
在我实现自己的鉴别器逻辑时,HelpDocument 和 LogEntry 之间没有创建任何关系。
所以我想要实现的是查询所有没有被解雇的 HelpDocuments。我可以用 sql 做到这一点,左外子查询连接如下:
SELECT HelpDocument.*, temp.*
FROM HelpDocument
LEFT OUTER JOIN(
    SELECT LogEntry.entity_id
    FROM LogEntry
    WHERE LogEntry.entityDiscriminator = 'HelpDocument'
    AND LogEntry.event = 'helpDocument.dismiss'
    AND LogEntry.entity_id = 11
) as temp ON HelpDocument.id = temp.entity_id
WHERE temp.entity_id IS NULL;
我的问题是,鉴于没有定义关系,我如何将其转换为 DQL?
更新的解决方案:
所以解决方案是不使用 LEFT OUTER JOIN,因为它们在 Doctrine2 中不存在/没有意义。最后我不得不做一个子查询连接:
/**
 * Filter by User Dismissed
 *
 * @param $qb
 * @param $route
 * @return mixed
 */
public function filterQueryByUserDismissed(QueryBuilder $qb, $args)
{
    $args = array_merge(array(
        "user" => null,
        "dismissed" => false
    ), $args);
    /** @var $dismissedQB QueryBuilder */
    $dismissedQB = $this->_em->createQueryBuilder();
    /*
    This line is important. We select an alternative attribute rather than
    letting Doctrine select le.id
    */
    $dismissedQB->select('le.entityId')
                ->from('\Mlf\AppBundle\Entity\UserEntityEventLog', 'le')
                ->where('le.entityDiscriminator = :entityDiscriminator')
                ->andWhere('le.event = :event')
                ->andWhere('le.user = :userId');
    $function = (true === $args['dismissed']) ? "in" : "notIn";
    $expr = $qb->expr()->$function($this->classAlias.'.id', $dismissedQB->getDQL());
    /** @var $qb QueryBuilder */
    $qb->andWhere($expr)
       ->setParameter("entityDiscriminator", HelpDocument::getDiscriminator())
       ->setParameter("event", HelpDocumentEvents::HELPDOCUMENT_DISMISS)
       ->setParameter("userId", $args["user"]);
//  exit($result = $qb->getQuery()->getSQL());
    return $qb;
}
此 DQL 查询产生以下 SQL:
SELECT h0_.id AS id0
FROM HelpDocument h0_ 
WHERE (
    h0_.id NOT IN (
        SELECT l1_.entity_id 
        FROM LogEntry l1_ 
        WHERE l1_.entityDiscriminator = 'helpDocument' 
        AND l1_.event = 'helpDocument.dismiss' 
        AND l1_.user_id = 1
    )
)
耶!