2013-03-13 112 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