2013-03-13 75 views
27

加入,我想使用Doctrine的查询生成器来构造SQL语句:主义查询生成器与条件

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的结构。提前致谢!

注意:我知道我们也可以用Doctrine编写native 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(); 
    } 
} 
+0

能否请你提供整个以下错误消息的作品? – hacfi 2013-03-13 07:27:07

+1

QueryException:[语法错误]第0行,第74列:错误:字符串的预期结束,'ON' – 2013-03-13 08:50:56

回答

61

我要回答我自己的问题。

  1. innerJoin应该使用关键字 “WITH”,而不是 “ON”(学说的文档是不准确的[13.2.6的辅助方法。]; [13.2.5 Expr的分类]是正确的)
  2. 没有必要以连接条件链接外键,因为它们已经在实体映射中指定。

因此,对我来说

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

您是否可以使用setParameters()函数完成它:phone和:username?我有一个'''无效的参数编号:绑定变量的数量与令牌的数量不匹配 – lrkwz 2015-11-09 14:01:50

+2

你把WITH和WHERE放在哪些条件? – 2017-03-08 00:47:43

8

可以明确有参加这样的:

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

但你需要使用类的命名空间,从理论加入:

use Doctrine\ORM\Query\Expr\Join; 

或者如果你喜欢那样:

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

否则,Join class不会被检测到,你的脚本会崩溃......

这里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(), 
    )); 

否则,我认为你是在执行上,并与,也许问题的混合。

+0

感谢您指出。但我确实有名字空间。我甚至直接尝试使用字符串'ON'。 – 2013-03-13 08:53:55

+0

你能告诉我们你写的完整查询(从头到尾)吗? – Sybio 2013-03-13 09:08:39

+0

我编辑了帖子。谢谢! – 2013-03-13 09:16:29