如何在教义2中使用WHERE IN


124

我有以下代码给我错误:

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

Answers:


114

在研究此问题时,我发现了一些对于遇到同一问题并寻求解决方案的人来说很重要的事情。

在原始帖子中,以下代码行:

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

将命名参数包装为数组会导致绑定参数编号问题。通过将其从数组包装中移除:

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

此问题应得到解决。这在以前版本的Doctrine中可能是个问题,但在最新版本的2.0中已解决。


5
我认为$qb->expr()->in()仅在Doctrine 2 ORM中存在,而在Doctrine DBAL中则没有。
马丁

3
$qb->expr()->in()确实在
DBAL

343

最简单的方法是将数组本身绑定为参数:

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

41
不仅如此,而且从2.1开始
MaciejPyszyński2012年

7
@MaciejPyszyński+1。最简单的方法通常是最好的方法!
AndrzejOśmiałowski14年

2
快速说明:默认情况下,此选项与-> setParameter('ids',$ ids)一起使用,而不与-> setParameters('ids'=> $ ids)一起使用。花了我几分钟的调试时间。
larrydahooster's

3
可以使用-> setParameters(...) ->where('b.status IN (:statuses)') ->setParameters([ 'customerId' => $customerId, 'storeId' => $storeId, 'statuses' => [Status::OPEN, Status::AWAITING_APPROVAL, Status::APPROVED] ]);
George Mylonas,

5
我想指出的驶过这是第3参数的重要性setParameter,以力Connection::PARAM_STR_ARRAY
吕克Wollants

58

并完成字符串解决方案

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

绝对是我的最佳解决方案:-)
Francesco Casula 2015年

3
如果您有整数数组而不是字符串,也可以使用\ Doctrine \ DBAL \ Connection :: PARAM_INT_ARRAY。
Omn,2015年


12

我知道这是一个过时的帖子,但可能会对某人有所帮助。我将通过回答有关整数的评论中提出的问题来投票表决并增强@Daniel Espendiller的答案

为了使int正常工作,请确保array中的值是int类型,可以在传递之前将强制类型转换为int。

 $qb->andWhere('foo.field IN (:ints)');
 $qb->setParameter('ints', array(1, 2), 
 \Doctrine\DBAL\Connection::PARAM_INT_ARRAY);

经过测试以选择/删除symfony 3.4和doctrine-bundle:1.8


8

我知道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 '17

6

做到这一点的最佳方法(尤其是在添加多个条件的情况下)是:

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

如果您的值数组包含字符串,则不能将setParameter方法与包含在内的字符串一起使用,因为引号将被转义!


6

这是我的用法:

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

5

发现如何在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
MihaiRăducanu16年

2

我更喜欢:

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

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

也适用于:

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

0

我在同样的场景中苦苦挣扎,因为我不得不对一组值进行查询。

以下为我工作:

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

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

数组数据示例(使用字符串和整数):

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

查询示例(适应您的需要):

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

$q->execute();

0

这是年后的今天,在传统的现场工作...对于我的生活,我不能得到->andWhere()->expr()->in()解决方案的工作。

最终查看了《主义》的mongodb-odb回购,并发现了一些非常具有启发性的测试:

public function testQueryWhereIn()
{ 
  $qb = $this->dm->createQueryBuilder('Documents\User');
  $choices = array('a', 'b');
  $qb->field('username')->in($choices);
  $expected = [
    'username' => ['$in' => $choices],
  ];
  $this->assertSame($expected, $qb->getQueryArray());
}

它为我工作!

您可以在github测试在这里。有助于澄清各种废话。

注意:据我所知,我的设置使用的是Doctrine MongoDb ODM v1.0.dev。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.