WHERE IN을 교리 2와 함께 사용하는 방법


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

1
이것이 권장되는 방법이라고 생각합니다. docs.doctrine-project.org/projects/doctrine-dbal/en/latest/…
martin

답변:


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에 있습니다
JamesHalsall 2015

344

이를 수행하는 가장 쉬운 방법은 배열 자체를 매개 변수로 바인딩하는 것입니다.

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

41
뿐만 아니라 2.1부터 시작
Maciej Pyszyński 2012-08-23

7
@ MaciejPyszyński +1. 가장 쉬운 방법은 종종 최고의 방법입니다!
Andrzej Ośmiałowski

2
빠른 언급 : 이것은-> setParameter ( 'ids', $ ids)에서는 기본적으로 작동하지만-> setParameters ( 'ids'=> $ ids)에서는 작동하지 않습니다. 디버깅하는 데 몇 분이 걸렸습니다.
larrydahooster 2015 년

3
> setParameters (...) - 메이크업에와 작품 ->where('b.status IN (:statuses)') ->setParameters([ 'customerId' => $customerId, 'storeId' => $storeId, 'statuses' => [Status::OPEN, Status::AWAITING_APPROVAL, Status::APPROVED] ]);
조지 Mylonas

5
나는 또한에 제 3 회 매개 변수를 전달의 중요성을 지적하고 싶습니다 setParameterConnection::PARAM_STR_ARRAY
뤽 Wollants을

58

완료를 위해 문자열 솔루션

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

:-) 나를 위해 확실히 최상의 솔루션
프란체스코 Casula

3
문자열이 아닌 정수 배열이있는 경우 \ Doctrine \ DBAL \ Connection :: PARAM_INT_ARRAY를 사용할 수도 있습니다.
Omn


12

나는 그것이 오래된 게시물이라는 것을 알고 있지만 누군가에게 도움이 될 수 있습니다. ints에 대한 의견에서 묻는 질문을 해결하여 @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 및 doctrine-bundle : 1.8에서 선택 / 삭제 테스트 완료


8

나는 OP의 예제가 DQL과 쿼리 빌더를 사용하고 있다는 것을 알고 있지만 컨트롤러 또는 저장소 클래스 외부에서 수행하는 방법을 찾고 있었으므로 다른 사람들에게 도움이 될 것입니다.

다음 WHERE IN과 같이 컨트롤러에서 a 를 수행 할 수도 있습니다 .

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

1
그것은 DQL을 사용하지 않고 where in을 수행하는 완벽하게 허용되는 방법이지만 그의 질문은 그의 DQL 코드와 관련이 있습니다. 그는 단순히 이러한 ID를 기반으로 모든 것을 제공하는 것 이상의 일을하고 있습니다.
spetz83

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)
미하이 Răducanu을

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/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 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를 사용하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.