Symfony : Pagination with inner join - php

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

Related

how to write sub-query in symfony doctrine

Am working on a symfony project with backend developed in doctrine & api-platform framework.I need to fetch some details along with checking a field in another table which will be a status. We use this status for handling something in front end.
I tried:-
$qb = $this->createQueryBuilder('contact');
$qb2=$qb;
$sub_query = $qb2->select('field')
->from('OtherTable','g')
->where("'id= '".$personId."'")
->OrderBy('updated_at', 'DESC')
->setMaxResults(1)
->getQuery()
->getResult();
$qb->select("contact.id,
contact.title,
count (distinct person.id) as
number_of_contacts_with_email',(".$sub_query.") as status")
->leftjoin('contact.people', 'person')
->leftJoin('person.jobs', 'jobs')
->groupBy('contact.id, contact.title');
$query=$qb->getQuery();
$result = $qb->getQuery()->getArrayResult();
return $result;
Am getting this error when executing query.
[Semantical Error] line 0, col 59 near 'OtherTable g': Error: Class 'OtherTable' is not defined.
How to write this sub query here?Is there any solution for this?
You should simply use the DQL of the subquery, as example:
// Don't take the query/result instances
$sub_query = $qb2->select('field')
->from('OtherTable','g')
->where("'id= '".$personId."'")
->OrderBy('updated_at', 'DESC')
->setMaxResults(1);
and use
$qb->select("contact.id,
contact.title,
count (distinct person.id) as
number_of_contacts_with_email',(".$sub_query->getDQL().") as status")
->leftjoin('contact.people', 'person')
->leftJoin('person.jobs', 'jobs')
->groupBy('contact.id, contact.title');
Hope this help

Doctrine2 QueryBuilder Join

So, I'm new to doctrine, and I'm trying to do a basic joint, but I guess I'm missing something, on my entities or I don't know for sure.
Doctrine Repository:
$queryBuilder = $this->createQueryBuilder()
->select('c.*, a.*')
->from('My\Entity\CompanyAdminNotes', 'c')
->innerJoin('Administrators','a','a.id = c.admin_id')
->where('c.admin_id = :admin_id')
->setParameter('admin_id', $id);
return $queryBuilder->getQuery()->getResult();
And I get the following error
Message: [Semantical Error] line 0, col 76 near 'a,
My\Entity\CompanyAdminNotes': Error: Identification Variable
Administrators used in join path expression but was not defined
before.
I'm not sure if my query it's wrong or something else isn't set. Can you guys give me a hint?
try to change this:
->innerJoin('Administrators','a','a.id = c.admin_id')
to this:
->innerJoin('My\Entity\Administrators','a','a.id = c.admin_id')
Because It need the path as you done into the from
UPDATE
Trying another solution like this:
$queryBuilder = $this->createQueryBuilder('c')
->select('c, a')
->from('My\Entity\CompanyAdminNotes', 'c')
->innerJoin('My:Administrators','a','a.id = c.admin_id')
->where('c.admin_id = :admin_id')
->setParameter('admin_id', $id);

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 [];
}

Join subquery with doctrine and Symfony 2

I saw the begining of an answer in a post about Zend : Join subquery with doctrine 2 DBAL
Unfortunately I can't manage it to work. I tried aimfeld soltuion like that:
$qbaudio = $em->createQueryBuilder();
$subSelect = $qbaudio->select ('a.id_support id_support','sum(a.duration) dureeTotale','count(a) nbAudio')
->from('MyBundle:AudioObject','a')
->groupBy('a.id_support')
->where('a.type = :audio_type')
->getQuery();
$qb = $em->createQueryBuilder();
$qb->select('sp.ref1','sp.title1','count(i) nbImage','sp.nbSupportSaisi','sum(a.duration) dureeTotale','count(a) nbAudio','a.sampling')
->from('MyBundle:Storage', 'st')
->leftJoin('p.sides','si')
->leftJoin('si.support','sp')
->leftJoin('sp.images','i')
->leftJoin('sp.audioObjects', sprintf('(%s)',$subSelect->getDQL()), 'a', 'ON sp.id = a.id_support')
->groupBy('sp.id')
->setParameter('audio_type', 'MP3')
Unfortunately I got this message :
Error: Expected end of string, got 'SELECT'
If it's possible with ZEnd, Why not with Symfony?
Any idea?
Thanks
Use SQL instead of DQL:
$subSelect->getSQL()

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