Подтвердить что ты не робот

Конструктор запросов Doctrine с использованием внутреннего соединения с условиями

Я хотел бы построить следующий SQL, используя конструктор запросов Doctrine:

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

Сначала я попробовал

$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');

Но я получаю следующую ошибку

Error: expected end of string, got 'ON'

Затем я попробовал

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

который, кажется, работает. Однако кто-нибудь знает, что случилось с первой попыткой? Я хотел бы сделать первую работу, поскольку она больше похожа на структуру SQL. Спасибо заранее!

Примечание. Я знаю, что мы также можем написать родной mysql или dql с помощью Doctrine, но я бы предпочел построитель запросов.

EDIT: Ниже приведен весь код

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();
    }
}
4b9b3361

Ответ 1

Я собираюсь ответить на свой вопрос.

  • innerJoin должен использовать ключевое слово "WITH" вместо "ON" (документация Doctrine [13.2.6. Методы помощника] неточна, [13.2.5. Класс Expr] правильный)
  • Не нужно связывать внешние ключи в состоянии соединения, поскольку они уже указаны в сопоставлении сущностей.

Поэтому для меня работает следующее

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

или

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

Ответ 2

Вы можете явно иметь такое соединение:

$qb->innerJoin('c.phones', 'p', Join::ON, 'c.id = p.customerId');

Но вам нужно использовать пространство имен класса Join from doctrine:

use Doctrine\ORM\Query\Expr\Join;

Или, если вы так предпочитаете:

$qb->innerJoin('c.phones', 'p', Doctrine\ORM\Query\Expr\Join::ON, 'c.id = p.customerId');

В противном случае Присоединить класс не будет обнаружен, а ваш script выйдет из строя...

Здесь конструктор метода innerJoin:

public function innerJoin($join, $alias, $conditionType = null, $condition = null);

Вы можете найти другие возможности (а не просто присоединиться к "ON", но также "WITH" и т.д.) здесь: http://docs.doctrine-project.org/en/2.0.x/reference/query-builder.html#the-expr-class

ИЗМЕНИТЬ

Думаю, что это должно быть:

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

    $qb->setParameters(array(
        'username' => $username,
        'phone' => $phone->getPhone(),
    ));

В противном случае, я думаю, вы выполняете сочетание ON и WITH, возможно, проблема.