如何将 WHERE IN 与 Doctrine 2 一起使用

问题描述 投票:0回答:14

我有以下代码,它给了我错误:

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')
php doctrine-orm query-builder
14个回答
417
投票

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

$queryBuilder->andWhere('r.winner IN (:ids)')
             ->setParameter('ids', $ids, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);

126
投票

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

来自原始帖子,以下代码行:

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

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

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

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


80
投票

并完成字符串解决方案

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

27
投票

我发现,尽管文档表明了这一点,让它发挥作用的唯一方法是这样的:

$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


24
投票

我知道这是一篇旧帖子,但可能对某人有帮助。我会通过解决有关整数的评论中提出的问题来投票并增强@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


11
投票

我知道 OP 的示例正在使用 DQL 和查询生成器,但我在寻找如何从控制器或存储库类外部执行此操作时偶然发现了这一点,所以也许这会对其他人有所帮助。

您还可以通过以下方式从控制器执行

WHERE IN

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

8
投票

这就是我的使用方法:

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

7
投票

执行此操作的最佳方法 - 特别是当您添加多个条件时 - 是:

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

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


7
投票

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


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

还适用于:

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

2
投票

我更喜欢:

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

0
投票

我在同样的场景中遇到了困难,我必须对一组值进行查询。

以下对我有用:

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();

0
投票

这是几年后的事了,在一个遗留网站上工作......我一生都无法让

->andWhere()
->expr()->in()
解决方案发挥作用。

最后查看了 Doctrine 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 here 上找到测试。对于澄清各种废话很有用。

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


-1
投票
$winnerIds = [1,3,5];
$qb->andWhere($qb->expr()->in('r.winner', ':winnerIds'))
   ->setParameter('winnerIds', $winnerIds)
;
© www.soinside.com 2019 - 2024. All rights reserved.