如何在原则2中使用 WHERE IN

我有下面的代码,给我的错误:

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')
236970 次浏览

我发现,不管医生怎么说,唯一的办法就是这样:

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

Http://groups.google.com/group/doctrine-dev/browse_thread/thread/fbf70837293676fb

在研究这个问题的过程中,我发现了一些对于任何遇到同样问题并寻找解决方案的人都很重要的东西。

从原文开始,代码如下:

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

将命名参数包装为数组会导致绑定参数编号问题:

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

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

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

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

做到这一点的最佳方法——尤其是当你添加了多个条件时——是:

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

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

为了完成串的解决方案

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

我更喜欢:

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

我是这么用的:

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

在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”语句中使用。

$qb->where($qb->expr()->in('r.winner', ':ids'))
->setParameter('ids', $ids);

同时与以下人士合作:

$qb->andWhere($qb->expr()->in('r.winner', ':ids'))
->setParameter('ids', $ids);

我知道 OP 的例子是使用 DQL 和查询构建器,但是我无意中发现这个例子是为了寻找如何在控制器或存储库类之外进行操作,所以这可能会对其他人有所帮助。

你也可以这样从控制器做一个 WHERE IN:

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

在这个场景中,我不得不对一个值数组执行查询。

以下几点对我很有效:

Http://docs.doctrine-project.org/projects/doctrine1/en/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();

我知道这是一个老职位,但可能有帮助的人。我会投票并加强@Daniel Espendiller 的回答,通过回答评论中关于 int 的问题

为了以适当的方式处理 int 类型的值,请确保数组中的值为 int 类型,您可以在传递..。

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

在 symfony 3.4和文本包: 1.8中测试了 select/delete

这是多年以后,工作在一个遗留的网站... 对我的生活,我不能得到的 ->andWhere()->expr()->in()解决方案的工作。

最后,我们查看了一下“蒙戈德-奥德回购原则”(Doctrine mongob-odb repo) ,发现了一些非常有启发性的测试:

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。

$winnerIds = [1,3,5];
$qb->andWhere($qb->expr()->in('r.winner', ':winnerIds'))
->setParameter('winnerIds', $winnerIds)
;