Doctrine- setting query parameters conditionally - php

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']);
}

Related

Symfony and Doctrine DQL query builder: how to use multiple setParameters inside if condition checks?

Using Symfony and Doctrine with the DQL query builder, I need to optionally add some WHERE conditions with parameters, with some if condition checks.
Pseudo code example:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb = $qb
->select('SOMETHING')
->from('SOMEWHERE')
->where('SOME CONDITIONS');
if ( SOME CHECK ) {
$qb
->andWhere('field1 = :field1')
->andWhere('field2 = :field2')
->setParameters([
'field1' => $myFieldValue1,
'field2' => $myFieldValue2,
]);
} else {
$qb
->andWhere('field1 = :field1')
->setParameters([
'field1' => $myOtherFieldValue1,
]);
}
Getting errors like:
Invalid parameter number: number of bound variables does not match number of tokens
Too few parameters: the query defines X parameters but you only bound Y
Too many parameters: the query defines X parameters and you bound Y
the cleanest solution to this problem I've found so far, is to wrap all the parameters inside an array and then calling only once the setParameters() method, checking if there is at least one parameter to set:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb = $qb
->select('SOMETHING')
->from('SOMEWHERE')
->where('SOME CONDITIONS')
$parameters = [];
if ( SOME CHECK ) {
$qb
->andWhere('field1 = :field1')
->andWhere('field2 = :field2');
$parameters['field1'] = $myFieldValue1;
$parameters['field2'] = $myFieldValue2;
} else {
$qb->andWhere('field1 = :field1');
$parameters['field1'] = $myOtherFieldValue1;
}
if (count($parameters)) {
$qb->setParameters($parameters);
}
You can set parameters one by one:
$qb
->setParameter('field1', $value1)
->setParameter('field2', $value2);
This way you'll be sure that you don't override other params with setParameters.

doctrine not exists subquery

I have in a repository this code:
public function getNotAssignedBy($speciality, $diploma)
{
$qb = $this->createQueryBuilder('j')
->select('DISTINCT(j.id) id', 'j.firstName', 'j.lastName', 'j.dateBirth', 'j.sex')
->leftJoin('j.qualifications', 'q')
;
if ($speciality) {
$qb->andWhere('q.speciality = :speciality_id')->setParameter('speciality_id', $speciality);
}
if ($diploma) {
$qb->andWhere('q.diploma = :diploma_id')->setParameter('diploma_id', $diploma);
}
$result = $qb->getQuery()->getResult();
return $result;
}
How can I get only rows where id not exists in another entity ??
Any help. Thanks
You can achieve it with something like this:
....
// construct a subselect joined with an entity that have a relation with the first table as example user
$sub = $this->createQueryBuilder();
$sub->select("t");
$sub->from("AnotherEntity","t");
$sub->andWhere('t.user = j.id');
// Your query builder:
$qb->andWhere($qb->expr()->not($qb->expr()->exists($sub->getDQL())));
Hope this help
Since I can't comment, so I will post a fixed version of #Matteo's solution
The correct way to use createQueryBuilder in this case is by using EntityManager. See my comment in the code below.
$sub = $this->_em->createQueryBuilder(); // _em stands for entity manager here. While $qb may use repositories createQueryBuilder() which requires alias
$sub->select("t");
$sub->from("AnotherEntity","t");
$sub->andWhere('t.user = j.id');
// Your query builder:
$qb->andWhere($qb->expr()->not($qb->expr()->exists($sub->getDQL())));

Symfony2 KNP Pagination "Cannot count query "

So , i'm working on a news portal . I'm using KNP Paginator,and i've got an error :
Cannot count query which selects two FROM components, cannot make distinction
And now , my source code :
#block of code from controller
$rep = $this->getDoctrine()->getRepository('NickCoreBundle:News');
$user = $this->get('security.context')->getToken()->getUser();
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$rep->getNewsFeedQuery($user->getId()),
$page,
10
);
and from my repository:
public function getNewsFeedQuery($userid)
{
$userid = intval($userid);
return $this->getEntityManager()->createQueryBuilder()
->select('n')
->from('NickCoreBundle:News', 'n')
->innerJoin('NickCoreBundle:Subscriptions', 's', 'WITH', 's.user = :userid AND n.source = s.source')
->orderBy("n.date","DESC")
->setParameter('userid', $userid)->getQuery();
}
how to solve it :) ? tried to get result from query , in ArrayCollection , it works (partialy,not sorted by date , and i think this method used a lot of time)
It's a little late to answer but it could be of help to other readers.
I would suggest doing away with the explicit innerJoin and let Doctrine handle the joins.
return $this->getEntityManager()->createQueryBuilder()
->select('n')
->from('NickCoreBundle:News', 'n')
->join('n.source', 's')
->where('s.user'= :userid )
->orderBy("n.date","DESC")
->setParameter('userid', $userid)->getQuery();

Symfony2 Query Builder Not Returning Many To One Value

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

Doctrine setParameter and Invalid parameter number

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

Categories