使用具有条件的内部联接的Doctrine查询构建器

Mr.*_* 14 36 sql symfony doctrine-orm

我想使用Doctrine的查询构建器构造以下SQL:

select c.*
from customer c
join phone p
on p.customer_id = c.id
and p.phone = :phone
where c.username = :username
Run Code Online (Sandbox Code Playgroud)

首先我试过了

$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');
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误

Error: expected end of string, got 'ON'
Run Code Online (Sandbox Code Playgroud)

然后我试了一下

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

这似乎有效.但是,有人知道第一次尝试有什么问题吗?我想让第一个工作,因为它更接近于SQL的结构.提前致谢!

注意:我知道我们也可以使用Doctrine编写本机mysql或dql,但我更喜欢查询构建器.

编辑:下面是整个代码

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Mr.*_* 14 83

我要回答我自己的问题.

  1. innerJoin应该使用关键字"WITH"而不是"ON"(Doctrine的文档[13.2.6.帮助方法]是不准确的; [13.2.5.Expr类]是正确的)
  2. 无需在连接条件中链接外键,因为它们已在实体映射中指定.

因此,以下对我有用

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

要么

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

  • 你可以用setParameters()完成它们:pho​​ne和:username?我有一个```无效的参数号:绑定变量的数量与令牌的数量``不匹配 (3认同)
  • 您在WITH与WHERE中放置了什么条件? (2认同)

Syb*_*bio 10

你可以明确地拥有这样的连接:

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

但是你需要使用类的Join命名空间:

use Doctrine\ORM\Query\Expr\Join;
Run Code Online (Sandbox Code Playgroud)

或者,如果你喜欢这样:

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

否则,将不会检测到Join类,并且您的脚本将崩溃...

这里是innerJoin方法的构造函数:

public function innerJoin($join, $alias, $conditionType = null, $condition = null);
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到其他可能性(不仅仅是加入"ON",还有"WITH"等...):http://docs.doctrine-project.org/en/2.0.x/reference/query-builder. HTML#的-EXPR级

编辑

认为它应该是:

$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(),
    ));
Run Code Online (Sandbox Code Playgroud)

否则我认为你正在执行ON和WITH的混合,也许是问题.

  • "使用Doctrine\ORM\Query\Expr\Join;"的+1.对于Symfony 2.8用户,我们需要使用WITH not ON.不支持On. (6认同)