I'm using Symfony2 and have a headache on ordering results by joined relations with QueryBuilder. I want to select a group by ID with ordered related items. Here's the code:
$rs = $this
->createQueryBuilder('a')
->select('a', 'c', 'm')
->leftJoin('a.item', 'c', Expr\Join::WITH, 'c.active = 1')
->leftJoin('c.media', 'm')
->where('a.id = :group_id')
// ->orderBy('c.sortOrder', 'asc')
->setParameter('group_id', $group_id)
->getQuery()
->getOneOrNullResult();
This way I get what I want, but items aren't ordered. If I uncomment line ->orderBy('c.sortOrder', 'asc'), I get empty result set. Tried to execute runnable query in PHPMyAdmin and both (with ordering and without) queries return same results, but one is ordered as it should be.
Is there any way to get relations ordered?
Related
I want to use the Doctrine's QueryBuilder to get Categories with a specified attribute and a number minimum of products inside. I precise that's the first time I use this Doctrine's function. I discovered that and I realized that it's so much powerful than basics repositories functions. I'm a very beginner with SQL because I used to use Repository's functions.
But I think I achieve this in pure SQL:
SELECT category.*,COUNT(*)
FROM category_product
INNER JOIN category ON category_product.category_id = category.id
WHERE category.name = 'region'
GROUP BY category_product.category_id HAVING COUNT(*) > 20
At the moment I'm totally lost with DQL construction. My Category and Product Entities both have a Many to Many relationship and I can't reach traducing this to Doctrine. I tried using the category_product table auto-generated by doctrine's but It doesn't want to access this table...
$qb = $this->createQueryBuilder('c');
$qb
->select('c')
->where("c.name = 'region'")
->innerJoin('c.products', 'p', 'WITH', 'COUNT(c.products) > :minimum')
->setParameter('minimum', $minimum);
dump($qb->getQuery(), $qb->getQuery()->getResult());
Each Time I uses a new construction I have Semantical errors I'm not able to correct...
Thanks a lot for your help
You could try some thing like here (piece of code from my working model)
$qb = $this->createQueryBuilder('c')
->select('c')
->where('c.name = region')
->addSelect('COUNT(c.products) AS counter')
->innerJoin('c.products', 'p')
->groupby('p.id')
->having('count(p.id) >= :minimum')
->setParameter('region', $region)
->setParameter('minimum', $minimum)
;
dump($qb->getQuery()->getResult());
related post: here
Ok Thanks to you I got it.
I shouldn't select the COUNT because I typed the return to be an Array of categories but it returned an array of arrays with contains the category and the count... I had to group by c too.
Thanks a lot for your help !
The answer is :
$qb = $this->createQueryBuilder('c')
->select('c')
->where('c.name = :region')
->innerJoin('c.products', 'p')
->groupBy('c')
->having('SIZE(c.products) > :minimum')
->setParameter('region', $region)
->setParameter('minimum', 20);
Having some problems retrieving ManytoOne relationships when using left join.
Before was using this query to query for conferences
$qb = $this->createQueryBuilder('u')
->select('u.id,u.comment,
IDENTITY(u.place) AS place_id,
IDENTITY(u.sponsor) AS sponsor_id,
IDENTITY(u.tour) AS tour_id,
u.startat
');
Now I'm trying to left join with diffusion which is tied to the diffusion in a many to many relationship.
$qbt = $this->createQueryBuilder('u')
->select('u','c')
->from('AppBundle:Conference', 'p')
->leftJoin('p.diffusion', 'c');
However this query doesn't return the u.place, u.sponsor and u.tour which are ManyToOne relationships.
leftJoin must be followed by 'WITH'. So for example:
->leftJoin('p.diffusion', 'p', 'WITH', 'p.user=u.id', 'u.id');
But i think it's better to post both your entities so i can give you the exact answer.
Found the issue , I had to add
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
to the getQuery , because getArrayResults by default doesn't return foreign keys( the place, sponsor and tour respectivly).
Here is my final query in the conference repository
$qbt = $this->_em->createQueryBuilder();
$qbt->select('conference','diffusion')
->from('AppBundle:Conference', 'conference')
->leftJoin('conference.diffusion', 'diffusion');
return $qbt
->getQuery()
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
->useQueryCache(true)
->useResultCache(true,3600)
->getArrayResult();
I've tried to find how to use column value as array key when getting results using queryBuilder. I found this question Using column value as array index in doctrine but unfortunately it doesn't work in my case as I'm using left join.
Currently I have this query:
$qb = $entityManager->createQueryBuilder('translation');
$qb->select('translation')
->from('MainBundle:PageTranslation', 'translation', 'translation.id')
->leftJoin('MainBundle:Page', 'page', 'WITH', 'IDENTITY(translation.page) = page.id')
->where('translation.locale = :locale')
->andWhere('translation.enabled = :enabled')
->andWhere('page.category = :category')
->setParameter('category', $category)
->setParameter('locale', $locale)
->setParameter('enabled', true);
$result = $qb->getQuery()->getResult();
Results I get has array keys starting with 0 and incrementing by one. I need array keys to be Page IDs (page.id) or IDENTITY of translation.page
If you look at the QueryBuilder API you'll see that the innerJoin() method has $indexBy as it's last argument. Pass 'translation.id' or ( the pk of translation instead of 'id') as the last argument, to get the desired result.
I use in my code a simple query that works fine in all the cases. This means that if the user has not a photo (for example) the query goes fine:
$user=$em->getRepository('UserBundle:User')->findOneById($id_user);
The entity User has a lot of relations with other entities, this is the reason to optimize the number of queries to avoid Doctrine's lazy loading. Then I make this query with DQL using QueryBuilder:
public function findUsuario($id_user){
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$qb->select('u, p, co, ci, f, s, q, b, r, se, com, t, beb, prof, v, h, i, idi, usf')
->from('UserBundle:User', 'u')
->innerJoin("u.pais", 'p')
->innerJoin("u.comunidad", 'co')
->innerJoin("u.ciudad", 'ci')
->innerJoin("u.fotos", 'f')
->innerJoin("u.sexo", 's')
->innerJoin("u.quiero", 'q')
->innerJoin("u.busco", 'b')
->innerJoin("u.relacionPareja", 'r')
->innerJoin("u.sexualidad", 'se')
->innerJoin("u.complexion", 'com')
->innerJoin("u.tabaco", 't')
->innerJoin("u.bebida", 'beb')
->innerJoin("u.profesion", 'prof')
->innerJoin("u.vivienda", 'v')
->innerJoin("u.hijo", 'h')
->innerJoin("u.ingreso", 'i')
->innerJoin("u.idiomas", 'idi')
->innerJoin("u.usuarioFavoritos", 'usf')
->where('u.id = :id')
->setParameter('id', $id_user);
$query= $qb->getQuery();
return $query->getSingleResult();
}
This works well when the user has information on all related entities, but if for example a user has no photo, the following exception occurs: "No result was found for query although at least one row was expected"
I don't understand why, can anyone shed some light? Thanks
An inner join should be used when you want all your rows to have data on the other side of the relationship, if no data exists on the other side of the relationship then the row will be omitted.
You can find more details about the different type of JOINs on this page.
Instead of the innerJoin method you will need to use the leftJoin method.
(Also, you have a bigger problem: you have way too many JOINs, I'd advise you to review the organization of your entities.)
I'd like show results of two tables but I have this Exception: "Cannot count query which selects two FROM components, cannot make distinction".
My query is:
$queryBuilder = $em->createQueryBuilder()
->select('e, e.id AS id, e.f14010101 AS f14010101, e.f14010105 AS f14010105')
->from('T140101Bundle\Entity\T140101', 'e')
->leftJoin('T140102Bundle\Entity\T140102', 'c', 'WITH', 'c.f14010201= e.id')
->groupBy('e.id');
Can you help me?