2011-05-08 76 views
95

我有下面的代碼,給我的錯誤:如何使用WHERE與學說2

Message: Invalid parameter number: number of bound variables does not match number of tokens 

代碼:

public function getCount($ids, $outcome) 
{ 
    if (!is_array($ids)) { 
     $ids = array($ids); 
    } 
    $qb = $this->getEntityManager()->createQueryBuilder(); 
    $qb->add('select', $qb->expr()->count('r.id')) 
     ->add('from', '\My\Entity\Rating r'); 
    if ($outcome === 'wins') { 
     $qb->add('where', $qb->expr()->in('r.winner', array('?1'))); 
    } 
    if ($outcome === 'fails') { 
     $qb->add('where', $qb->expr()->in('r.loser', array('?1'))); 
    } 
    $qb->setParameter(1, $ids); 
    $query = $qb->getQuery(); 
    //die('q = ' . $qb); 
    return $query->getSingleScalarResult(); 
} 

數據(或$ IDS):

Array 
(
    [0] => 566 
    [1] => 569 
    [2] => 571 
) 

DQL結果:

q = SELECT COUNT(r.id) FROM \My\Entity\Rating r WHERE r.winner IN('?1') 
+1

我認爲這是推薦的方式http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion – martin 2013-09-16 14:49:18

回答

91

在研究這個問題,我發現的東西,將是重要的任何人遇到同樣的問題並尋找解決方案。

從原始訊息,下面的行的代碼:

$qb->add('where', $qb->expr()->in('r.winner', array('?1'))); 

包裝紙命名參數作爲數組使綁定參數數目的問題。通過將其從陣列包裝中刪除:

$qb->add('where', $qb->expr()->in('r.winner', '?1')); 

應該修復此問題。這可能是以前版本的Doctrine中的一個問題,但它在2.0的最新版本中已修復。

+2

謝謝,解決了它。使用2.1.3 – Tjorriemorrie 2012-01-08 08:05:08

+5

我認爲'$ qb-> expr() - > in()'只在Doctrine 2 ORM中,但不在Doctrine DBAL中。 – martin 2013-09-16 14:48:30

+1

'$ qb-> expr() - > in()'確實在DBAL – JamesHalsall 2015-11-09 10:38:41

266

做到這一點的最簡單的方法是通過陣列本身結合作爲一個參數:

$queryBuilder->andWhere('r.winner IN (:ids)') 
      ->setParameter('ids', $ids); 
+40

不僅從2.1 – 2012-08-23 10:33:33

+5

@MaciejPyszyński+1開始。最簡單的方法往往是最好的! – 2014-02-06 22:09:57

+1

快速提及:此功能默認使用 - > setParameter('ids',$ ids),但不能用 - > setParameters('ids'=> $ ids)。花了我幾分鐘的調試。 – larrydahooster 2015-09-29 14:59:32

6

最好的辦法這樣做 - 特別是如果你添加多個條件 - 是:

$values = array(...); // array of your values 
$qb->andWhere('where', $qb->expr()->in('r.winner', $values)); 

如果您的值數組包含字符串,則不能將setParameter方法與imploded字符串一起使用,因爲您的引號將被轉義!

45

,並完成串解

$qb->andWhere('foo.field IN (:string)'); 
$qb->setParameter('string', array('foo', 'bar'), \Doctrine\DBAL\Connection::PARAM_STR_ARRAY); 
+0

對我來說絕對是最好的解決方案:-) – 2015-02-11 16:02:18

+2

如果你有一個整數不是字符串的數組,也可以使用\ Doctrine \ DBAL \ Connection :: PARAM_INT_ARRAY。 – Omn 2015-02-25 22:30:53

+0

@Omn我不能讓它與一個整數數組一起工作。 – 2016-04-04 17:48:44

2

我喜歡:

$qb->andWhere($qb->expr()->in('t.user_role_id', [ 
    User::USER_ROLE_ID_ADVERTISER, 
    User::USER_ROLE_ID_MANAGER, 
])); 
5

這是我如何使用它:

->where('b.status IN (:statuses)') 
->setParameters([ 
       'customerId' => $customerId, 
       'storeId' => $storeId, 
       'statuses' => [Status::OPEN, Status::AWAITING_APPROVAL, Status::APPROVED] 
      ]); 
4

找到如何做到這一點在今年2016: https://redbeardtechnologies.wordpress.com/2011/07/01/doctrine-2-dql-in-statement/

報價:

下面是如何正確地做到這一點:

$em->createQuery(「SELECT users FROM Entities\User users WHERE users.id IN (:userids)」) 
->setParameters(array(‘userids’ => $userIds)); 

的setParameters將採取陣列,妥善爆它在使用的「IN」的聲明。

+2

這解決了我的問題(圍繞':userids'的括號) – 2016-09-27 14:01:36

0
->where($qb->expr()->in('foo.bar', ':data')) 
      ->setParameter('participants', $data); 

還與工作原理:

->andWhere($qb->expr()->in('foo.bar', ':users')) 
       ->setParameter('data', $data); 
3

我知道OP的例子是使用DQL和查詢生成器,但我偶然發現了這個尋找如何從控制器或外部存儲庫的做上課,所以也許這會幫助別人。

你也可以做從控制器WHERE IN這樣:

// Symfony example 
$ids = [1, 2, 3, 4]; 
$repo = $this->getDoctrine()->getRepository('AppBundle:RepoName'); 
$result = $repo->findBy([ 
    'id' => $ids 
]); 
+1

這是一種完全可以接受的方式,可以在不使用DQL的情況下進行操作,但他的問題是參考他的DQL代碼。他所做的不僅僅是簡單的給我所有基於這些ID的事情。 – spetz83 2017-03-31 16:07:58

0

我,我必須做一個查詢對值的數組這種相同的情況下掙扎。

以下爲我工作:

$ids = array(1, 2, 3, 4); 

查詢例子(適應在你需要它):

http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/dql-doctrine-query-language.html#where-clause

->andWhereIn("[fieldname]", [array[]]) 

陣列數據爲例(與字符串和整數工作) :

$q = dataTable::getInstance() 
    ->createQuery() 
    ->where("name = ?",'John') 
    ->andWhereIn("image_id", $ids) 
    ->orderBy('date_created ASC') 
    ->limit(100); 

$q->execute();