带有教义的查询构建器中的外部联接

Posted

技术标签:

【中文标题】带有教义的查询构建器中的外部联接【英文标题】:outer join in a query builder with doctrine 【发布时间】:2015-09-10 08:40:25 【问题描述】:

我有一个名为 PointsComptage.php 的实体和另一个名为 Compteurs.php 的实体。

这是它们之间的关系:

// Compteurs.php 
/**
 * @var \PointsComptage
 *
 * @ORM\ManyToOne(targetEntity="PointsComptage", inversedBy="compteurs")
 * @ORM\JoinColumns(
 *   @ORM\JoinColumn(name="pointscomptage_id", referencedColumnName="id")
 * )
 */
private $pointsComptage;

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\OneToMany(targetEntity="ParametresMesure", mappedBy="compteurs")
 */
private $parametresMesure;

/*  ...  */


// PointsComptage.php
/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\OneToMany(targetEntity="Compteurs", mappedBy="pointsComptage")
 */
private $compteurs;

/*  ...  */

这是我的存储库实体中的查询,用于恢复具有某一点Comptage 属性的compteurs:

$queryBuilder = $this->_em->createQueryBuilder();

$queryBuilder
  ->select ('c')
  ->from('MySpaceMyBundle:Compteurs', 'c')
  ->leftJoin('c.pointsComptage', 'pc')
  ->join('c.parametresMesure', 'pm')
  ->join('pm.typesUnite', 'tu')
  ->join('pm.typesParametre', 'tp')
  ->where('c.pointsComptage = pc.id')
  ->andWhere('pm.compteurs = c.id')
  ->andWhere('pm.typesUnite = tu.id')
  ->andWhere('pm.typesParametre = tp.id')
  ->andWhere('c.pointsComptage = :id')
  ->add('orderBy', 'c.miseEnService', 'ASC')
  ->setParameter('id', $id);

  return $queryBuilder->getQuery()
                      ->getResult();

问题是我为所选的 pointComptage 恢复了我的compteurs,但只有具有parametresMesure 关系的compteurs。

在我的数据库中,可能一个compteur 没有 parametreMesure 数据

如何恢复没有parametresMesure的compteurs和有parametresMesure属性的compteurs(在同一个queryBuilder中)?

我在教义文档中读到,queryBuilder 中的 leftJoin 的工作方式类似于外连接。

我正在尝试做的是恢复与所选pointComptage 相关联的所有compteurs,无论parametresMesure 是否。

【问题讨论】:

如果您在 SO 中搜索“教条外连接”,则有几个答案。其中之一几乎肯定会对您有所帮助。 只需使用leftJoin 而不是join @PiWi 即使我在 queryBuilder 中使用 leftJoin 而不是 join,我的请求也会返回相同的结果,即只有具有 parametresMesure 的 compteurs ,但是对于之前选择的 pointComptage,我有一个没有 parametresMesurecompteur 【参考方案1】:

我找到了解决方案。问题是我在Where 子句中添加了条件,但我需要在leftJoin 中指定它们。

这是我的代码以了解我所做的事情:

$queryBuilder = $this->_em->createQueryBuilder();

$queryBuilder
    ->select ('c')
    ->from('MySpaceMyBundle:Compteurs', 'c')
    ->leftJoin('c.pointsComptage', 'pc', 'WITH', 'pc.id = c.pointsComptage')
    ->leftJoin('c.parametresMesure', 'pm', 'WITH', 'pm.compteurs = c.id')
    ->leftJoin('pm.typesUnite', 'tu', 'WITH', 'pm.typesUnite = tu.id')
    ->leftJoin('pm.typesParametre', 'tp', 'WITH', 'pm.typesParametre = tp.id')
    ->andWhere('c.pointsComptage = :id')
    ->add('orderBy', 'c.miseEnService', 'ASC')
    ->setParameter('id', $id);

return $queryBuilder->getQuery()
                    ->getResult();

这样我恢复了我所有的compteurs,即使他们没有parametresMesure

【讨论】:

你自己找到的 :-) 我只是在自己写这个答案 ;-) 如果你使用左连接,这比最终的过滤效果更好。 你能解释一下为什么我们不使用 ->Having('pc.id = c.pointsComptage') 来代替 WITH 吗?

以上是关于带有教义的查询构建器中的外部联接的主要内容,如果未能解决你的问题,请参考以下文章

将带有变量的闭包传递给 Laravel 查询构建器中的 where 方法

Zend - 教义 2 查询构建器帮助

关于与查询构建器的“一对多”关系的教义内连接

谓词构建器组和/或带有内部外部的查询

php 带有附件ID的布局构建器中的facetwp自定义字段

首先在doctrine查询构建器中选择完全匹配