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(); } }
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.
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.
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.
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.
I'm going to answer my own question.
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');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With