diff --git a/lib/Doctrine/ORM/QueryBuilder.php b/lib/Doctrine/ORM/QueryBuilder.php index 13d041e2b..3dfc2754b 100644 --- a/lib/Doctrine/ORM/QueryBuilder.php +++ b/lib/Doctrine/ORM/QueryBuilder.php @@ -96,6 +96,11 @@ class QueryBuilder */ private $_maxResults = null; + /** + * @var array Keeps root entity alias names for join entities. + */ + private $joinRootAliases = array(); + /** * Initializes a new QueryBuilder that uses the given EntityManager. * @@ -219,6 +224,32 @@ class QueryBuilder ->setMaxResults($this->_maxResults); } + /** + * Finds the root entity alias of the joined entity. + * + * @param string $alias The alias of the new join entity + * @param string $parentAlias The parent entity alias of the join relationship + * @return string + */ + private function findRootAlias($alias, $parentAlias) + { + $rootAlias = null; + + if (in_array($parentAlias, $this->getRootAliases())) { + $rootAlias = $parentAlias; + } elseif (isset($this->joinRootAliases[$parentAlias])) { + $rootAlias = $this->joinRootAliases[$parentAlias]; + } else { + // Should never happen with correct joining order. Might be + // thoughtful to throw exception instead. + $rootAlias = $this->getRootAlias(); + } + + $this->joinRootAliases[$alias] = $rootAlias; + + return $rootAlias; + } + /** * Gets the FIRST root alias of the query. This is the first entity alias involved * in the construction of the query. @@ -667,11 +698,9 @@ class QueryBuilder */ public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) { - $rootAlias = substr($join, 0, strpos($join, '.')); + $parentAlias = substr($join, 0, strpos($join, '.')); - if ( ! in_array($rootAlias, $this->getRootAliases())) { - $rootAlias = $this->getRootAlias(); - } + $rootAlias = $this->findRootAlias($alias, $parentAlias); $join = new Expr\Join( Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy @@ -703,11 +732,9 @@ class QueryBuilder */ public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) { - $rootAlias = substr($join, 0, strpos($join, '.')); + $parentAlias = substr($join, 0, strpos($join, '.')); - if ( ! in_array($rootAlias, $this->getRootAliases())) { - $rootAlias = $this->getRootAlias(); - } + $rootAlias = $this->findRootAlias($alias, $parentAlias); $join = new Expr\Join( Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php new file mode 100644 index 000000000..77f32907e --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php @@ -0,0 +1,92 @@ +_em->createQueryBuilder(); + /* @var $qb \Doctrine\ORM\QueryBuilder */ + + $qb->select('_a') + ->from(__NAMESPACE__ . '\DDC1757A', '_a') + ->from(__NAMESPACE__ . '\DDC1757B', '_b') + ->join('_b.c', '_c') + ->join('_c.d', '_d'); + + $q = $qb->getQuery(); + $dql = $q->getDQL(); + + // Show difference between expected and actual queries on error + self::assertEquals("SELECT _a FROM " . __NAMESPACE__ . "\DDC1757A _a, " . __NAMESPACE__ . "\DDC1757B _b INNER JOIN _b.c _c INNER JOIN _c.d _d", + $dql, + "Wrong DQL query"); + } +} + +/** + * @Entity + */ +class DDC1757A +{ + /** + * @Column(type="integer") + * @Id + * @GeneratedValue(strategy="AUTO") + */ + private $id; +} + +/** + * @Entity + */ +class DDC1757B +{ + /** + * @Column(type="integer") + * @Id + * @GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @OneToOne(targetEntity="DDC1757C") + */ + private $c; +} + +/** + * @Entity + */ +class DDC1757C +{ + /** + * @Column(type="integer") + * @Id + * @GeneratedValue(strategy="AUTO") + */ + public $id; + + /** + * @OneToOne(targetEntity="DDC1757D") + */ + private $d; +} + +/** + * @Entity + */ +class DDC1757D +{ + /** + * @Column(type="integer") + * @Id + * @GeneratedValue(strategy="AUTO") + */ + public $id; +}