After many tries, I think I finally know the documentation by heart.
Then, I need your help .. I don't understand why Doctrine show me this error :
Invalid parameter number: number of bound variables does not match
number of tokens
Here is my code :
$qb = $this->em->createQueryBuilder();
$qb->select('m')
->from('Entities\Marque', 'm')
->leftJoin('m.magasin', 'ma')
->where('m.nom = :marque AND ma.nom LIKE :magasin')
->setParameter('marque', $marque)
->setParameter('magasin', '%'.$matchesNumber[1].'%');
$results = $qb->getQuery()->getArrayResult();
Thank you in advance for your answer.
This also happens if you accidentally use more than one where(), which happened to me once.
$em = $this->getEntityManager();
$query = $em->createQueryBuilder()
->from('AppBundle:SomeEntity', 's')
->select('s')
->where('s.foo = :foo')
->where('s.bar = :bar') // <- HERE
->setParameter('foo', 'Foo Value')
->setParameter('bar', 'Bar Value');
Should be:
$em = $this->getEntityManager();
$query = $em->createQueryBuilder()
->from('AppBundle:SomeEntity', 's')
->select('s')
->where('s.foo = :foo')
->andWhere('s.bar = :bar') // <- CHANGE TO andWhere()
->setParameter('foo', 'Foo Value')
->setParameter('bar', 'Bar Value');
Hope this helps someone.
I presume ->setParameter overrides the previous one.
For multiple Parameters use:
->setParameters(['key1' => $value1, 'key2' => $value2])
See Doctrine Upgrade:
From now on, parameters in queries is an ArrayCollection instead of a simple array. This >affects heavily the usage of setParameters(), because it will not append anymore parameters >to query, but will actually override the already defined ones. Whenever you are retrieving a >parameter (ie. $query->getParameter(1))
Doctrine Upgrade Description
Maybe that also applies to setParameter?
I'm so sorry .. I just found my error .. Later, like more later in my code .. I type a new query with my old "$qb" ..
I'm such a noob !
$qb = $this->em->createQueryBuilder();
$parameters = array('marque'=>$marque, 'magasin'=>'%'.$matchesNumber[1].'%');
$qb->select('m')
->from('Entities\Marque', 'm')
->leftJoin('m.magasin', 'ma')
->where('m.nom = :marque')
->andWhere('ma.nom LIKE :magasin')
->setParameters($parameters);
$results = $qb->getQuery()->getArrayResult();
Related
Hi I'm using PHP Silex with Doctrine DBAL query builder (no ORM) and SQLite. It sort of works, so I can build a query and it spits back results, but I for the life of me I can't get setting parameters to work (I get empty array all the time).
Here's what works:
$qb->select('*')
->from('photos')
->where("country = '".$country."'")
->andWhere('status = 1')
->orderBy($sort[0], $sort[1])
->setFirstResult($start)
->setMaxResults($limit)
For obvious reasons I would like to replace that with:
$qb->select('*')
->from('photos')
->where("country = ?") /// <--
->andWhere('status = 1')
->orderBy($sort[0], $sort[1])
->setFirstResult($start)
->setMaxResults($limit)
->setParameter(0, $country) /// <--
Or:
$qb->select('*')
->from('photos')
->where("country = :country") /// <--
->andWhere('status = 1')
->orderBy($sort[0], $sort[1])
->setFirstResult($start)
->setMaxResults($limit)
->setParameter(':country', $country) /// <--
Or even:
$qb = $this->db->createQueryBuilder();
$expr = $qb->expr();
$qb->select('*')
->from('photos')
->where($qb->expr()->andX(
$qb->expr()->eq('country', '?1'), /// <--
$qb->expr()->eq('status', 1)
))
->orderBy($sort[0], $sort[1])
->setFirstResult($start)
->setMaxResults($limit)
->setParameter(1, $country) /// <--
These are all examples of setting params I found in the docs, however none of them seems to work and I'm not sure how to debug that. Checking $qb->getSQL() and $qb->getParams() doesn't seem to show anything useful.
Im using ("doctrine/dbal": "~2.2") if that matters.
I came back to my own question by accident cause I solved it long time ago and of course it turned out to be a silly thing. The problem lied not in building the query properly but using it the right way. Here's the answer for future reference.
With Query Builder you don't do:
$this->db->fetchAll($qb->getSQL());
// you get query with unfilled placeholders
but rather:
$qb->execute()->fetchAll();
Thanks to all who tried to help!
I building application in Symfony 2.
I have to filter users basing on data passed in form.
I wrote something like this in my controller:
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->addSelect('user');
$qb->from('Application\Sonata\UserBundle\Entity\User', 'user');
if(($filter['freelancer'])){
$qb->setParameters(array('freelancer' => $filter['freelancer']))
->andWhere('user.firstname = :freelancer');
}
if(($filter['category'])){
$qb->innerJoin('Flexihub\MainBundle\Entity\Category', 'category', 'WITH', 'user.category = category.id')
->setParameters(array('category' => $filter['category']))
->andWhere('user.category = :category');
}
$query = $qb->getQuery();
$result = $query->getResult();
dump($result);
Im stuck with error when im trying to pass both parameters.
Invalid parameter number: number of bound variables does not match number of tokens
What am I doing wrong?
Is there better solution to solve my problem?
It's logical to write it like this, so, first add criteria then provide arguments:
if(($filter['freelancer'])){
$qb
->andWhere('user.firstname = :freelancer')
->setParameter('freelancer', $filter['freelancer']);
}
if(($filter['category'])){
$qb
->innerJoin('Flexihub\MainBundle\Entity\Category', 'category', 'WITH', 'user.category = category')
->andWhere('user.category = :category')
->setParameter('category', $filter['category']);
}
Before I begin, I believe I have tried everything from this previous post: How to use WHERE IN with Doctrine 2
So I have a Silex application connected to a MySQL DB using Doctrine via composer (doctrine/dbal 2.2.*)
The query builder I am trying to run is this:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->select('DAY(datefield1) x, COUNT(*) value')
->from('table1', 's')
->join('s', 'table2', 't', 't.key=s.key')
->where('MONTH(datefield1) = :billMonth')
->andWhere('YEAR(datefield1) = :billYear')
->andWhere('t.key IN (:keylist)')
->groupBy('x')
->orderBy('x', 'asc')
->setParameter(':billMonth', $month)
->setParameter(':billYear', $year)
->setParameter(':keylist', implode(",", $keylist))
->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
The parameters are (month=8)(year=2014)(keylist=array(1,2,3,4))
The query does not fail but it curiously doesn't contain all the data that it should.
I have tried ->setParameter(':keylist', $keylist) to use the raw array, and this didn't work.
I have tried this kind of syntax too:
$qb->add('where', $qb->expr()->in('r.winner', array('?1')));
However that threw up an error because the in method wasn't available in expression builder class.
Please will someone cast an eye over this and save me from having to hardcode my SQL?
OK seeing as this old thread has seen some action since I last looked I wanted to confirm that the issue is long resolved - a third parameter in setParameter allows you to inform Doctrine how to handle the array:
$qb = $this->db->createQueryBuilder();
$stmt = $qb
->select('*')
->from(self::DB_TABLE, 'x')
->where('x.service IN (:services)')
->orderBy('x.session_end', 'DESC')
->addOrderBy('x.direction', 'DESC')
->setParameter(':services', $services, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
->setFirstResult($offset)
->setMaxResults($count)
->execute();
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
DB placeholders/parameters are for single values. You're passing in a monolithic string 1,2,3,4 due to calling implode() on the array. Given:
WHERE t.key IN (:keylist)
then this query will be executed as the equivalent of
WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
Since it's a string, and only one single string in the IN clause, it's the functional equivalent of
WHERE t.key = '1,2,3,4'
and not the
WHERE (t.key = 1 OR t.key = 2 OR ....)
you want it to be. Either set up multiple parameters, one for each value in your array, or embed your string in the query directly
->andWhere('t.key IN (' . implode(',', $keylist) . ')')
which of course opens you up to sql injection attack vulnerabilities.
If you build the sql query yourself you can use DBAL's PARAM_INT_ARRAY type:
use Doctrine\DBAL\Connection as DB;
$db->executeQuery('SELECT DAY(datefield1) x, COUNT(*) value
FROM table1 s
JOIN table2 t ON t.key=s.key
WHERE MONTH(datefield1) = :billMonth
AND YEAR(datefield1) = :billYear
AND t.key IN (:keylist)
GROUP BY x
ORDER BY x ASC',
array(':billMonth' => $month, ':billYear' => $year, ':keylist' => $keylist),
array(':billMonth' => \PDO::PARAM_INT, ':billYear' => \PDO::PARAM_INT, ':keylist' => DB::PARAM_INT_ARRAY
)->fetchAll(\PDO::FETCH_ASSOC);
Correct way to handle such IN clause is as simple as it can be:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->(...)
->andWhere('t.key IN (:keylist)')
->setParameter(':keylist', $keylist)
->getQuery()
->getArrayResult();
I have used this dozen times and it works - doctrine is smart enough to handle your $keylist being array.
Other thing is that I don't know why you're using fetchAll method which is reduntant here - execute() is just enough. Maybe this is a root of your problem.
My suggestion: try to fire action in dev mode (app_dev.php) and check your app/logs/dev.log - you will find all sql queries performed. Verify that database returns data which you are expecting from Doctrine.
->add('where', $qb->expr()->andX(
$qb->expr()->in('r.winner', ':winner')
))
->setParameters(array(
"winner" => $winners,
"billMonth", $month,
// add all params here
));
You should use the in expression via the querybuilder like below, and change how you set the parameter:
->andWhere($qb->expr()->in('t.key', ':keylist'))
The complete code:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->select('DAY(datefield1) x, COUNT(*) value')
->from('table1', 's')
->join('s', 'table2', 't', 't.key=s.key')
->where('MONTH(datefield1) = :billMonth')
->andWhere('YEAR(datefield1) = :billYear')
->andWhere('t.key')
->andWhere($qb->expr()->in('t.key', ':keylist'))
->groupBy('x')
->orderBy('x', 'asc')
->setParameter(':billMonth', $month)
->setParameter(':billYear', $year)
->setParameter(':keylist', $keylist)
->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
I want to set null to a field in doctrine and here is the sentence
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$query = $qb->update('Model\Example', 'u')->set('u.deletedAt', ':deletedAt')
->where("u.id IN (:ids)")->setParameter('deletedAt', null)
->setParameter('ids', $ids)
->getQuery();
$query->execute();
i think that this code should do the job, but im getting this exception
An exception occurred while executing 'UPDATE example SET deleted_at = ?
WHERE (id IN (?)) AND (example.deleted_at IS NULL)' with params
[null, "5,6"]: SQLSTATE[22P02]: Invalid text representation: 7 ERROR:
la sintaxis de entrada no es válida para integer: «5,6»
first of all why doctrine is adding that AND (example.deleted_at IS NULL) am i doing something wrong ?
Your original query looks like it should work. I duplicated and tested with:
$em = $this->getService('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->update('Cerad\Bundle\PersonBundle\Entity\Person','person');
$qb->set('person.verified',':verified');
$qb->setParameter('verified',null);
$qb->where('person.id IN (:ids)');
$qb->setParameter('ids',array(1,2,3));
echo $qb->getQuery()->getSql(); // UPDATE persons SET verified = ? WHERE id IN (?)
$qb->getQuery()->execute();
Works as expected.
Are you sure you copy/pasted your exact code? No editing after the fact? Verify your ids array really is an array of integers. That is the only spot I could see where there might be an issue. And do make sure your error is coming from the code you posted. Maybe something else is going on? Try isolating your code in a command object. And of course deletedAt has it's is nullable set to true?
There is no real need to use the expr object for this case. Doctrine 2 correctly handles arrays for IN statements.
====================================
I suspect you have $ids = '5,6'? Try setting it to: $ids = array(5,6); Though even with a string I don't see how it's messing up the query.
When you set the value with PHP null script , it's not understood for doctrine because when transforming to the native sql ,he will not replace null with null value as string , so to resolve , pass the null value as string like
$qb->set('q.deletedAt','NULL');
thanks #Cerad the problem was that i was using the soft-delete extension from StofDoctrineExtensionsBundle and the bundle was adding the soft delete filter, so i just disabled the soft delete filter and now it works as expected,posting the solution many thanks.
$em = $this->getDoctrine()->getManager();
$em->getFilters()->disable('softdeleteable'); // this was the problem when you use the soft delete extension you need to disable the filter if you want to reactivate deleted records
$qb = $em->createQueryBuilder();
$qb->update('Model\Example', 'q');
$qb->set('q.deletedAt',':deletedAt');
$qb->setParameter('deletedAt',null);
$qb->where("q.id IN (:ids)");
$qb->setParameter('ids', $ids);
the problem is that you $ids is a string. you can make:
$arrayOfIds = explode(",", $ids);
and after in you update query:
->setParameter('ids', $arrayOfIds)
I have an entity that has a column "inventoryLcoation_id" that has a many to one relationship. For some reason when I use createQueryBuilder() it is not returning that value in my ajax call, but it returns everything else: id, name, etc etc.. This is not an issue with Symfony2, its an issue with my lack of knowledge :)
Here is my query builder code:
$qb = $this
->createQueryBuilder('p')
->select('p.id', 'p.name')
->where('p.inventoryLocation = :inventoryId')
->andWhere('p.account = :account_id')
->setParameter('inventoryId', $value)
->setParameter('account_id', $account_id)
->orderBy('p.id', 'DESC');
if($qb->getQuery()->getArrayResult()){
return $qb->getQuery()->getArrayResult();
}else{
return false;
}
What do I need to code to have it also include the value from the inventoryLocation table which is mapped to the column value "inventoryLocation_id"?
Thanks so much for your help in enlightening my understanding to the awesome world of Symfony2!
try a join:
$qb->join('p.inventoryLocation','i')
and in the select especify both entities
$qb->select('p','i')
it should look like this:
$qb = $this
->createQueryBuilder('p')
->select('p','i')
->join('p.inventoryLocation','i')
->where('p.inventoryLocation = :inventoryId') // or ->where('i = :inventoryId')
->andWhere('p.account = :account_id')
->setParameter('inventoryId', $value)
->setParameter('account_id', $account_id)
->orderBy('p.id', 'DESC');