Update query with LIMIT ( setMaxResults ) in doctrine2 using createQueryBuilder not working - php

I have the following code
$qb = $this->createQueryBuilder('cs')
->update()
->set('cs.is_active', 1)
->where('cs.reward_coupon = :reward_coupon')
->setMaxResults($limit)
->setParameter('reward_coupon', $rewardCoupon);
$qb->getQuery()->execute();
This doesn’t apply the LIMIT in the resultant query.

setMaxResult() has to be your last Doctrine statement in order to properly works
example :
$qb = $this->createQueryBuilder('cs')
->update()
->set('cs.is_active', 1)
->where('cs.reward_coupon = :reward_coupon')
->setParameter('reward_coupon', $rewardCoupon)
->setMaxResults($limit);
return $qb->getQuery()->execute();

I think that this may help
$limit=50;
$i=0;
$qb = $this->createQueryBuilder('cs')
->update()
->set('cs.is_active', 1)
->where('cs.reward_coupon = :reward_coupon')
->setParameter('reward_coupon', $rewardCoupon)
->setFirstResult($i)
->setMaxResults($limit);
$qb->getQuery()->execute();

Related

Is there any way to "free" the Doctrine2 QueryBuilder object?

I am running into an interesting issue and now I am curious about the "why". Maybe this Doctrine2 related, maybe it's not, maybe is just OOP.
Take a look to the following Doctrine Repository function:
public function generateOrderPush(int $quote_id): array
{
$group_quote_id = $this->getEntityManager()->getRepository('QuoteBundle:Quote')->find($quote_id)->getGroupQuoteId();
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$header = $qb->select(['q.quoteId','q.othersQuoteId','IDENTITY(q.distributor)'])
->from('QuoteBundle:Quote', 'q')
->where('q.quoteType =:quote_type')
->andWhere('q.groupQuoteId =:group_quote_id')
->setParameter('quote_type', 'current')
->setParameter('group_quote_id', $group_quote_id)
->setMaxResults(1)
->orderBy('q.quoteId', 'ASC')
->getQuery()
->getArrayResult();
$details = $qb->select(['qt.quoteId', 'qt.othersQuoteId', 'IDENTITY(qt.customer)'])
->from('QuoteBundle:Quote', 'qt')
->join('QuoteBundle:QuoteDetail', 'qd', 'WITH', 'qt.quoteId = qd.quoteId')
->where('qt.quoteType =:quote_type')
->andWhere('qt.groupQuoteId =:group_quote_id')
->setParameter('quote_type', 'current')
->setParameter('group_quote_id', $group_quote_id)
->groupBy('qd.renewalPartNumber')
->orderBy('qt.quoteId', 'ASC')
->getQuery()
->getArrayResult();
return [];
}
The first query $header is executed properly and I got data back. The second query $details is failing as error below show:
SELECT q0_.quote_id AS quote_id_0, q0_.QuoteID AS QuoteID_1,
q0_.CustomerSiteID AS sclr_2, FROM quote q1_ INNER JOIN quote_detail
q2_ ON (q0_.quote_id = q2_.quote_id), quote q0_ WHERE q0_.quote_type =
? AND q0_.group_quote_id = ? GROUP BY q2_.RenewalPartNumber ORDER BY
q0_.quote_id ASC LIMIT 1' with params ["current", 1428]:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'q0_.quote_id' in
'on clause'
I think somehow Doctrine keep|think I am referring to the first object (from previous) query when I am not since I have added a new alias for the second query qt.
A solution to the issue could be split this into two different functions but before get into that one, I would like to know why is this happening and if there is any other way than mine to fix the problem.
Use a different queryBuilder object:
public function generateOrderPush(int $quote_id): array
{
$group_quote_id = $this->getEntityManager()->getRepository('QuoteBundle:Quote')->find($quote_id)->getGroupQuoteId();
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$anotherQb = $em->createQueryBuilder();
$header = $qb->select(['q.quoteId','q.othersQuoteId','IDENTITY(q.distributor)'])
->from('QuoteBundle:Quote', 'q')
->where('q.quoteType =:quote_type')
->andWhere('q.groupQuoteId =:group_quote_id')
->setParameter('quote_type', 'current')
->setParameter('group_quote_id', $group_quote_id)
->setMaxResults(1)
->orderBy('q.quoteId', 'ASC')
->getQuery()
->getArrayResult();
$details = $anotherQb->select(['qt.quoteId', 'qt.othersQuoteId', 'IDENTITY(qt.customer)'])
->from('QuoteBundle:Quote', 'qt')
->join('QuoteBundle:QuoteDetail', 'qd', 'WITH', 'qt.quoteId = qd.quoteId')
->where('qt.quoteType =:quote_type')
->andWhere('qt.groupQuoteId =:group_quote_id')
->setParameter('quote_type', 'current')
->setParameter('group_quote_id', $group_quote_id)
->groupBy('qd.renewalPartNumber')
->orderBy('qt.quoteId', 'ASC')
->getQuery()
->getArrayResult();
return [];
}

Doctrine delete the oldest entry

I have one MongoDb document with 3 fields message, author, sendAt, i have created a query builder to count all DB entries on this document and if there is more than 20 entries, I'm trying to delete the oldest one.
sendAt is the current dateTime when the message is send ("sendAt" : ISODate("2016-01-21T08:53:00Z"))
I have an unfinished query builder
public function deleteOldestMessage()
{
return $this->createQueryBuilder()
->delete('m')
->from('Messages', 'm')
->where('m.sendAt = ')
->execute();
}
But i really don't know what i should add on the where condition.
I should maybe order DESC the sendAt field and delete the first on the list ?
How can I tell the query builder to delete the oldest one ?
Thanks,
You need first to select the oldest one then you can delete it like this :
$qb->select('m')
->from('Messages', 'm')
->orderBy('m.sendAt', 'DESC');
$messages = $qb->getResult();
thene
if(count($messages) >= 20){
//get the first element of array which is the oldest one
$lastMessage = current($messages);
$em->remove($lastMessage);
}
You can try something like:
$qb = $em->createQueryBuilder();
$messages = $qb->select('m')
->from('Messages', 'm')
->orderBy('m.sendAt', 'ASC')
->getQuery()
->getResult()
;
// You will receive array where in the top will be the oldest message.
if (count($messages) > 20) {
// And in your desired case, you can remove just one oldest message.
$messageToDelete = array_shift($messages);
$em->remove($lastMessage);
$em->flush();
}
You use sql query builder options instead of mongodb.
return $this->createQueryBuilder()
->remove()
->sort('sendAt', 'asc')
->getQuery()
->getSingleResult()
->execute();

Symfony : Pagination with inner join

I need to implement a pagination. Seemingly, Doctrine doesn't support some jointures.
Here is my query :
$query = $this->getEntityManager()
->createQueryBuilder();
$query->setFirstResult(($page - 1) * $maxperpage);
$query->setMaxResults($maxperpage);
$query->select('d')
->from('DemandeBundle:Declaration', 'd')
->orderBy('d.id', 'ASC')
->innerJoin('ContactBundle:Contact', 'c', 'WITH', 'd.contact = c')
->where('c.structure_id = :structure_id')
->setParameter('structure_id', $structureId)
->getQuery()
->getResult();
return new Paginator($query, true);
It's working fine when I am not using innerJoin but I need to use it so as to display only requests regarding to my user.
Using innerJoin I got that kind of error :
"An exception has been thrown during the rendering of a template
("Cannot count query which selects two FROM components, cannot make distinction") in
DemandeBundle:Demande:listing_demande.html.twig at line 25"
How can I circumvent this problem without using another bundle or whatever.
Hope you will understand me guy.
Is your Declaration somehow related to Contact?
It's far better for you to have ManyToOne relation in Contact that points to Declaration. That way, it will work since you won't have two FROM components, but single one instead.
Then, modify the query to do:
->innerJoin('d.contant', 'c')
The full query should look like this:
$query->select('d')
->from('DemandeBundle:Declaration', 'd')
->orderBy('d.id', 'ASC')
->innerJoin('d.contact', 'c') // <-- THIS LINE IS CRITICAL
->where('c.structure_id = :structure_id')
->setParameter('structure_id', $structureId)
->getQuery()
->getResult();
Finally, I found out a solution :
Instead of :
$query->select('d')
->from('DemandeBundle:Declaration', 'd')
->orderBy('d.id', 'ASC')
->innerJoin('ContactBundle:Contact', 'c', 'WITH', 'd.contact = c')
->where('c.structure_id = :structure_id')
->setParameter('structure_id', $structureId)
->getQuery()
->getResult();
I used :
$query->select('d')
->add('from', 'SgaDemandeBundle:Declaration d INNER JOIN d.contact c')
->where('c.structure_id = :structure_id')
->setParameter('structure_id', $structureId)
->orderBy('d.id', 'ASC')
->getQuery();

Symfony2 & Doctrine - Get number of rows returned from datasource

I have the following code in my Symfony2 Repository Class...
$query = $this->createQueryBuilder('foo')
->where('foo.bar = :id')
->setParameter('id', $myID)
->getQuery();
How do I get the number of rows found by the database?
Thanks in advance
You need to execute DQL to do something you want.
$query = $this->createQueryBuilder()
->from('foo', 'f')
->where('foo.bar = :id')
->setParameter('id', $myID)
->getQuery();
$total = $query->select('COUNT(f)')
->getQuery()
->getSingleScalarResult();
I think you can do something like that:
$query = $this->createQueryBuilder()
->select('COUNT(f.id)')
->from('foo', 'f')
->where('foo.bar = :id')
->setParameter('id', $myID)
->getQuery();
$total = $query->getSingleScalarResult();
You execute the query then get the results. When you have the results, you get the number of record by doing a count on the results:
$results = $query->getResult();
$resultCount = count($results);
If you are concerned with paging, like getting 25 records out of the total. Then, you have two choices.
You perform the query twice, one time to get total results, another time to retrieve only 25 results using the method setFirstResult and setMaxResults. This method setFirstResult enable you to set the offset and the second, setMaxResults, number of records. The following code will give you results ranging from 25 to 50, it's the second page if you use 25 records by page.
$query->setFirstResult(25);
$query->setMaxResults(25);
You can check doctrine-extensions for Doctrine2 which have paginator support. These extensions have been made by one of the developer of Doctrine2. You can review these here.
Hope this help.
Regards,
Matt
I think this is as concise as it gets:
$qb = $repo->createQueryBuilder('entity');
$qb->select('COUNT(entity)');
$count = $qb->getQuery()->getSingleScalarResult();
Where $repo is of type Doctrine\ORM\EntityRepository

How to select distinct query using symfony2 doctrine query builder?

I have this symfony code where it retrieves all the categories related to a blog section on my project:
$category = $catrep->createQueryBuilder('cc')
->Where('cc.contenttype = :type')
->setParameter('type', 'blogarticle')
->getQuery();
$categories = $category->getResult();
This works, but the query includes duplicates:
Test Content
Business
Test Content
I want to use the DISTINCT command in my query. The only examples I have seen require me to write raw SQL. I want to avoid this as much as possible as I am trying to keep all of my code the same so they all use the QueryBuilder feature supplied by Symfony2/Doctrine.
I tried adding distinct() to my query like this:
$category = $catrep->createQueryBuilder('cc')
->Where('cc.contenttype = :type')
->setParameter('type', 'blogarticle')
->distinct('cc.categoryid')
->getQuery();
$categories = $category->getResult();
But it results in the following error:
Fatal error: Call to undefined method Doctrine\ORM\QueryBuilder::distinct()
How do I tell symfony to select distinct?
This works:
$category = $catrep->createQueryBuilder('cc')
->select('cc.categoryid')
->where('cc.contenttype = :type')
->setParameter('type', 'blogarticle')
->distinct()
->getQuery();
$categories = $category->getResult();
Edit for Symfony 3 & 4.
You should use ->groupBy('cc.categoryid') instead of ->distinct()
If you use the "select()" statement, you can do this:
$category = $catrep->createQueryBuilder('cc')
->select('DISTINCT cc.contenttype')
->Where('cc.contenttype = :type')
->setParameter('type', 'blogarticle')
->getQuery();
$categories = $category->getResult();
you could write
select DISTINCT f from t;
as
select f from t group by f;
thing is, I am just currently myself getting into Doctrine, so I cannot give you a real answer. but you could as shown above, simulate a distinct with group by and transform that into Doctrine. if you want add further filtering then use HAVING after group by.
Just open your repository file and add this new function, then call it inside your controller:
public function distinctCategories(){
return $this->createQueryBuilder('cc')
->where('cc.contenttype = :type')
->setParameter('type', 'blogarticle')
->groupBy('cc.blogarticle')
->getQuery()
->getResult()
;
}
Then within your controller:
public function index(YourRepository $repo)
{
$distinctCategories = $repo->distinctCategories();
return $this->render('your_twig_file.html.twig', [
'distinctCategories' => $distinctCategories
]);
}
Good luck!

Categories