Compare a count of subquery with scalar - symfony

I'm using Symfony 4.3 and I have a problem in my DQL query.
The purpose of my query is to select email of user how have list of right for this is my DQL query:
$qb = $this->createQueryBuilder('u')
->select('u.email,u.id')
->leftJoin('u.profile', 'profile')
->leftJoin('u.country', 'country')
->leftJoin('profile.privileges', 'pri')
->leftJoin('pri.ressource', 'resource')
$checkRightQuery = $this->em->createQueryBuilder()
->select('count(rc)')
->from(Ressource::class, 'rc')
->leftJoin('rc.privileges', 'privil')
->leftJoin('privil.profile', 'prof')
->leftJoin('prof.user', 'user')
->where( $this->em->getExpressionBuilder()->in('rc.actionFront', ':rights'))
->andWhere('user.id =u.id');
$qb->andWhere(
$this->em->getExpressionBuilder()->eq(count($rights),
$checkRightQuery
)
);
$qb->setParameters(['rights' => $rights]);
The problem is when I take the result of the count it's not a scalar and it can't compare it to scalar.
Any help please?

Try using parenthesis on your condition with the subquery:
$qb->andWhere(
$this->em->getExpressionBuilder()->eq(count($rights),
'(' . $checkRightQuery . ')'
)
);
References
Doctrine return error with “eq”, no with “in”

Related

DISTINCT Statement is not working in Doctrine

I try get distinct rows from doctrine, but it not work (uniq hotels)
$qb = $this->createQueryBuilder('self');
$qb
->distinct('hotel')
->join('self.hotel', 'hotel')
->where('self.request = :id')
->setParameter('id',$requestId);
return $qb->getQuery()->getResult();
This DQL returns all hotels.
SQL qwery from Symfony:
I want this qwery:
SELECT count(DISTINCT hotel_id) FROM symfony.search_result where request_id=#requrst_id
Based on your update the DQL you want to build is this
$qb = $this->createQueryBuilder('self');
$qb
->select($qb->expr()->countDistinct('hotel.id'))
->join('self.hotel', 'hotel')
->where('self.request = :id')
->setParameter('id',$requestId);
return $qb->getQuery()->getSingleScalarResult();
note that i changed the
->distinct('hotel') to ->select($qb->expr()->countDistinct('hotel.id'))
also i changed the
getResult() to getSingleScalarResult()
now it will return just one result with the count of the unique hotel_ids

Symfony and Doctrine: order by time difference

I am trying to build a query that retrieves all the most recent and upcoming activities from database.
The entity activity has a field named date of type DateTime. So in my repository I was thinking of building something like this:
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, NOW())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
Unfortunately I get the following error:
[Syntax Error] line 0, col 59: Error: Expected end of string, got '('
The Dql that is generated by my query:
SELECT a FROM MyBundle\Entity\Activity a ORDER BY DATEDIFF( a.date, NOW()) ASC
I also tried installing beberlei/DoctrineExtensions, but either it is not working or I was unable to configure it correctly.
Anyone has any suggestion?
Thanks in advance
date_diff si already implemented as Doctrine DQL statement as described here
for use as ordering statement I suggest you to use the HIDDEN select keyword as explained in this article
So your DQL is like this:
SELECT
a,
DATE_DIFF( a.date, CURRENT_TIMESTAMP() ) AS HIDDEN score
FROM MyBundle:Entity a
ORDER BY score
And add the max result on the query. Let me know if you need help to adapt as query builder statement
Hope this help
Why don't you just use
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, CURRENT_TIMESTAMP())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
?

Symfony doctrine using column value as array key when using joins

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.

How to use a query builder object inside an IN clause of another query builder object

I need to create a query builder expression that use an IN statement where I want to put another query create by querybuilder too. In DQL, the query that i can get is:
SELECT u
FROM BundleUsuarioBundle:Usuario u
WHERE u.id IN (
SELECT u2.id
FROM BundleTramiteBundle:ExamenTeorico et
JOIN et.usuarioHabilitacion u2
WHERE u2.centro = :centro
) ORDER BY u.apellido ASC, u.nombre ASC
but i dont use that because I need put that in 'query_builder' option of an entity field of a form. So, i need a QB but I dont know how I can nest querybuilder expressions. I actually have the two queries in QueryBuilder format but separated:
$qb = $this->em->createQueryBuilder();
$qb
->select('usuario_habilitacion.id')
->from('BundleTramiteBundle:ExamenTeorico', 'examen_teorico')
->join('examen_teorico.usuarioHabilitacion', 'usuario_habilitacion');
$user = $this->getUser();
if ( !$this->esTipoASPV($user) ) {
$centro = $this->getCentro();
$qb
->andWhere($qb->expr()->eq('usuario_habilitacion.centro', ':centro'))
->setParameter(':centro', $centro->getId());
}
and:
$er
->createQueryBuilder('u')
->where($qb->expr()->in('u.id', ___???___ ))
->addOrderBy("u.apellido", "ASC")
->addOrderBy("u.nombre", "ASC");
You can get the result of your sub-query inside the first query but calling getDQL() and placing it inside a where clause in your first query. Make sure you select the id in the sub-query.
Example:
$qb->andWhere($qb->expr()->in('u.id', $er->getDQL()))

'where not in' query with doctrine query builder

Im trying to reproduce this query:
SELECT * FROM `request_lines`
where request_id not in(
select requestLine_id from `asset_request_lines` where asset_id = 1
)
in doctrine query builder,
I am stuck on the where request_id not in(select
I currently have:
$linked = $em->createQueryBuilder()
->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where()
->getQuery()
->getResult();
You need to use query builder expressions, and this means you need access to the query builder object. Also, the code is easier to write if you generate the subselect list ahead of time:
$qb = $em->createQueryBuilder();
$nots = $qb->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($qb->expr()->eq('arl.asset_id',1))
->getQuery()
->getResult();
$linked = $qb->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($qb->expr()->notIn('rl.request_id', $nots))
->getQuery()
->getResult();
It is possible to do this in one Doctrine query:
$qb = $this->_em->createQueryBuilder();
$sub = $qb;
$sub = $qb->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($qb->expr()->eq('arl.asset_id',1));
$linked = $qb->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($qb->expr()->notIn('rl.request_id', $sub->getDQL()))
->getQuery()
->getResult();
Check the reference in this answer here
Using Symfony 5, this solution might help those, who are trying to set parameters on a subquery, the notIn() 2nd argument accepts an array or you could pass a DQL instead and that's what we are doing here and keep in mind that the parameters should be added to the main query as below.
$main = $this->em->createQueryBuilder();
$sub = $main;
$sub = $sub->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($sub->expr()->eq('arl.asset_id',':id'));
$linked = $main->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($main->expr()->notIn('rl.request_id', $sub->getDQL()))
->setParameter('id', 1)
->getQuery()
->getResult();

Resources