如何在Doctrine 2中使用WHERE IN

Tjo*_*rie 117 php query-builder doctrine-orm

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

Message: Invalid parameter number: number of bound variables does not match number of tokens 
Run Code Online (Sandbox Code Playgroud)

码:

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();
}
Run Code Online (Sandbox Code Playgroud)

数据(或$ ids):

Array
(
    [0] => 566
    [1] => 569
    [2] => 571
)
Run Code Online (Sandbox Code Playgroud)

DQL结果:

q = SELECT COUNT(r.id) FROM \My\Entity\Rating r WHERE r.winner IN('?1')
Run Code Online (Sandbox Code Playgroud)

Mac*_*ski 323

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

$queryBuilder->andWhere('r.winner IN (:ids)')
             ->setParameter('ids', $ids);
Run Code Online (Sandbox Code Playgroud)

  • 不仅仅是从2.1开始 (41认同)
  • @MaciejPyszyński+ 1.最简单的方法通常是最好的方法! (6认同)
  • 我想指出将第3个参数传递给`setParameter`以强制`Connection :: PARAM_STR_ARRAY`的重要性. (5认同)
  • 使用 - > setParameters(...)``` - > where('b.status IN(:statuses)') - > setParameters(['customerId'=> $ customerId,'storeId'=> $ storeId,'statuses'=> [Status :: OPEN,Status :: AWAITING_APPROVAL,Status :: APPROVED]]);``` (3认同)
  • 快速提及:默认使用 - > setParameter('ids',$ ids)但不使用 - > setParameters('ids'=> $ ids).我花了几分钟的调试时间. (2认同)

小智 111

在研究这个问题时,我发现了一些对于遇到同样问题和寻找解决方案的人来说很重要的事情.

从原帖,以下代码行:

$qb->add('where', $qb->expr()->in('r.winner', array('?1')));
Run Code Online (Sandbox Code Playgroud)

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

$qb->add('where', $qb->expr()->in('r.winner', '?1'));
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为`$ qb-> expr() - > in()`只在Doctrine 2 ORM中,但不在Doctrine DBAL中. (5认同)
  • `$ qb-> expr()-> in()`确实在DBAL中 (3认同)

Dan*_*ler 55

并完成字符串解决方案

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

  • 如果你有一个整数数组而不是字符串,也可以使用\ Doctrine\DBAL\Connection :: PARAM_INT_ARRAY. (3认同)

Jer*_*cks 24

我发现,尽管文档指出,但实现这一点的唯一方法是:

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

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


Azh*_*tak 10

我知道这是一个老帖子,但可能对某人有帮助.我会通过在有关整数的评论中提出的问题来投票和提升@Daniel Espendiller的答案

为了使int适当地工作,确保数组中的值是int类型,你可以在传递之前键入cast to int ...

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

在symfony 3.4和doctrine-bundle中测试选择/删除:1.8


Cal*_*ane 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)
);
Run Code Online (Sandbox Code Playgroud)

该方法setParameters将采用给定的数组并将其正确内爆以在“IN”语句中使用。

  • 这解决了我的问题(`:userids` 周围的括号) (3认同)

Yes*_*rry 7

我知道OP的例子是使用DQL和查询构建器,但我偶然发现了这个从控制器或存储库类外部查找的方法,所以这可能会对其他人有所帮助.

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

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


Geo*_*nas 6

这就是我使用它的方式:

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


ck1*_*ck1 5

这样做的最佳方式 - 特别是如果你要添加多个条件 - 是:

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

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