Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine query builder using inner join with conditions

I'd like to construct the following SQL using Doctrine's query builder:

select c.* from customer c join phone p on p.customer_id = c.id and p.phone = :phone where c.username = :username 

First I tried

$qb->select('c')     ->innerJoin('c.phones', 'p', Join::ON, $qb->expr()->andx(         $qb->expr()->eq('p.customerId', 'c.id'),         $qb->expr()->eq('p.phone', ':phone')     ))     ->where('c.username = :username'); 

But I'm getting the following error

Error: expected end of string, got 'ON' 

Then I tried

$qb->select('c')     ->innerJoin('c.phones', 'p')     ->where('c.username = :username')     ->andWhere('p.phone = :phone'); 

which seems to be working. However, does anyone know what's wrong with the first attempt? I'd like to make the first one work since it resembles more closely to how SQL is structured. Thanks in advance!

Note: I know we can also write native mysql or dql with Doctrine, but I'd prefer query builder.

EDIT: Below is the entire code

namespace Cyan\CustomerBundle\Repository;  use Cyan\CustomerBundle\Entity\Customer; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query\Expr\Join;  class CustomerRepository extends EntityRepository {     public function findCustomerByPhone($username, $phone)     {         $qb = $this->createQueryBuilder('c');          $qb->select('c')             ->innerJoin('c.phones', 'p', Join::ON, $qb->expr()->andx(                 $qb->expr()->eq('p.customerId', 'c.id'),                 $qb->expr()->eq('p.phone', ':phone')             ))             ->where('c.username = :username');  //        $qb->select('c') //            ->innerJoin('c.phones', 'p') //            ->where('c.username = :username') //            ->andWhere('p.phone = :phone');          $qb->setParameters(array(             'username' => $username,             'phone' => $phone->getPhone(),         ));          $query = $qb->getQuery();         return $query->getResult();     } } 
like image 972
Mr. 14 Avatar asked Mar 13 '13 04:03

Mr. 14


People also ask

Can we put condition on inner join?

To use the WHERE clause to perform the same join as you perform using the INNER JOIN syntax, enter both the join condition and the additional selection condition in the WHERE clause. The tables to be joined are listed in the FROM clause, separated by commas.

Can you join with or condition?

If you have an OR condition in the JOIN - and there is no possibility that the values in the OR statement overlap...then you can convert it to a UNION ALL. If the values overlap it would require a UNION which may not improve performance over the JOIN.

Does inner join need a WHERE clause?

INNER JOIN ON vs WHERE clause Linking between two or more tables should be done using an INNER JOIN ON clause but filtering on individual data elements should be done with WHERE clause. INNER JOIN is ANSI syntax whereas the WHERE syntax is more relational model oriented.

What is on condition in joins?

The purpose of the ON clause is to specify the join conditions, that is, to define how the tables should be joined. Specifically, you define how the records should be matched.


1 Answers

I'm going to answer my own question.

  1. innerJoin should use the keyword "WITH" instead of "ON" (Doctrine's documentation [13.2.6. Helper methods] is inaccurate; [13.2.5. The Expr class] is correct)
  2. no need to link foreign keys in join condition as they're already specified in the entity mapping.

Therefore, the following works for me

$qb->select('c')     ->innerJoin('c.phones', 'p', 'WITH', 'p.phone = :phone')     ->where('c.username = :username'); 

or

$qb->select('c')     ->innerJoin('c.phones', 'p', Join::WITH, $qb->expr()->eq('p.phone', ':phone'))     ->where('c.username = :username'); 
like image 146
Mr. 14 Avatar answered Sep 27 '22 21:09

Mr. 14