how to write sub-query in symfony doctrine - php

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

Related

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

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

order by LENGTH

In Symfony 1.4 and Doctrine 1.2 i can:
$bodies = Doctrine::getTable('Body')->createQuery('b')
->where('b.visible = 1')
->orderBy('LENGTH(b.title) ASC')
->execute();
and then working ok.
In Symfony 2 and Doctrine 2 i have:
$bodies = $this->getDoctrine()
->getRepository('MainBodyBundle:Body')
->createQueryBuilder('b')
->where('b.visible = 1')
->orderBy('LENGTH(b.title)', 'ASC')
->getQuery()
->getResults();
but this not working, i have error:
An exception has been thrown during the rendering of a template
("[Syntax Error] line 0, col 114: Error: Expected end of string, got
'('") in "MainBodyBundle::index.html.twig".
If you want to order by string length you should user LENGTH function in select:
$bodies = $this->getDoctrine()
->getRepository('MainBodyBundle:Body')
->createQueryBuilder('b')
->select('b,LENGTH(b.title) lgth')
->where('b.visible = 1')
->orderBy('lgth', 'ASC')
->getQuery()
->getResults();
The error in this case seems to be a syntax error and is coming from the twig file not the repository or controller. So i think the you should first check your index.html.twig for a syntax error rather than checking the query.

Laravel using UNION in query builder

I have an SQL query that works fine and I'm trying to convert into fluent::
SELECT DISTINCT tags.tag
FROM tags, items
WHERE tags.taggable_type = 'Item'
AND items.item_list_id = '1'
UNION
SELECT DISTINCT tags.tag
FROM tags, itemlists
WHERE tags.taggable_type = 'ItemList'
AND itemlists.id = '1'
This is what I have so far in fluent, it all seems right as far as I can tell from the docs and the individual queries both work on their own, it's just when I UNION them it throws an error:
$itemTags = Tag::join('items', 'items.id', '=', 'tags.taggable_id')
->select('tags.tag')
->distinct()
->where('tags.taggable_type', '=', 'Item')
->where('items.item_list_id', '=', $itemList->id);
$itemListTags = Tag::join('itemlists', 'itemlists.id', '=', 'tags.taggable_id')
->select('tags.tag')
->distinct()
->where('tags.taggable_type', '=', 'ItemList')
->where('itemlists.id', '=', $itemList->id);
// the var_dump below shows the expected results for the individual queries
// var_dump($itemTags->lists('tag'), $itemListTags->lists('tag')); exit;
return $itemTags
->union($itemListTags)
->get();
I get the following error when I run it (I've also swapped from Ardent back to Eloquent on the model in case that made a difference - it doesn't):
Argument 1 passed to Illuminate\Database\Query\Builder::mergeBindings() must be an instance of Illuminate\Database\Query\Builder, instance of LaravelBook\Ardent\Builder given, called in path/to/root\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php on line 898 and defined
Looks like your models are using Ardent, not Eloquent:
...instance of LaravelBook\Ardent\Builder given, ...
And probably this might be a problem on Ardent, not Laravel.
Open an issue here: https://github.com/laravelbook/ardent.
EDIT:
Try to change use QueryBuilder instead of Eloquent:
Use this for QueryBuilder:
DB::table('tags')->
Instead of the Eloquent way:
Tag::
I know you mentioned wanting to use the query builder, but for complex queries that the builder might throw fits on, you can directly access the PDO object:
$pdo = DB::connection()->getPdo();

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

Categories