Doctrine DQL query rewrite to Query Builder - doctrine-orm

I have query
$Select = 'SELECT COUNT(o.Id) FROM Entities\Order o';
How to rewrite this query for query builder?
$qb = $this->entityManager->createQueryBuilder();
$qb->select(.....
Thanks

It is very straight forward as you can see in the documentation.
$qb = $this->entityManager->createQueryBuilder();
$result = $qb->select('COUNT(o.Id)')
->from('Entities\Order', 'o')
->getQuery()
->getResult();
If you just want to have the number in $result you can use
$qb = $this->entityManager->createQueryBuilder();
$result = $qb->select('COUNT(o.Id)')
->from('Entities\Order', 'o')
->getQuery()
->getSingleScalarResult();

Related

How is it possible to map column names from a Doctrine sql query?

I created a query with query builder like this:
$qb = $em->createQueryBuilder();
$qb->select(['u.id', 'u.name'])
->from(User::class, 'u')
->where('u.active = 1')
;
$sql = $qb->getQuery()->getSql();
The result looks like this:
SELECT u1_.user_id as s1, u1_.full_name as s2 FROM users u1_ WHERE u1_.is_active = 1
I would like to execute it as a native query, but I have to find out, how to map s1, s2 to id, name.
you have to use as inside your select
using your example =>
$qb = $em->createQueryBuilder();
$qb->select(['u.id as s1', 'u.name as s2'])
->from(User::class, 'u')
->where('u.active = 1');
$sql = $qb->getQuery()->getSql();
this maps id to s1 and name as s2
Not sure I understand your question but if you want to run a native query with, in the result, the columns id and name, you can replace them in the query, they're aliases so they can be anything you want :
SELECT u.user_id as id, u.full_name as name FROM users u WHERE u.is_active = 1

DQL getResult return array

I'm playing with Doctrine, and I think I probably miss something.
So I have a table for some relations, and here is the columns:
id | user_id | workshop_id
Basically, I use this table to know that a user is register for a workshop.
I want to count how many users subscribe for a workshop.
So in my Repository, I use a DQL request:
/** #var EntityManager $entityManager */
$entityManager = $this->getEntityManager();
$query = $entityManager->createQuery("
SELECT COUNT('uw.id')
FROM App\Entity\UserWorkshops AS uw
LEFT JOIN App\Entity\User AS u WITH u.userId = uw.user
WHERE uw.workshop = :workshop_id");
$count = $query
->setParameters(['workshop_id' => $workshopId])
->getResult();
And here, and example of the result:
I just need to retrieve 3, as an integer.
How can I return something different ?
thanks
You can use getSingleScalarResult, from the doc:
Query#getSingleScalarResult(): Retrieves a single scalar value from
the result returned by the dbms. If the result contains more than a
single scalar value, an exception is thrown. The pure/mixed
distinction does not apply.
As example:
$count = $query
->setParameters(['workshop_id' => $workshopId])
->getSingleScalarResult();

Left Join with NOT IN clause and QueryBuilder

i'm trying to convert a query to DQL or build ir with query builder.
I can retrive with success the results from database with the following query:
SELECT * FROM flag
left join countries
on flag.id = countries.flag
where countries.flag IS NULL
Now, i need to conver this to DQL or build it with queryBuilder.
My entities are Country and Flag. The entity Country as a field flag as a external id.
So far, i got the following code:
$qb = $em->createQueryBuilder();
$available =
$qb
->select('f')
->from('Flag', 'f')
->leftJoin('Countries', 'c', 'ON', 'c.flag = f.id')
->where('f.id IS NULL');
My dump of $available doesnt return anything.
What's whong with this QueryBuilder?
Thanks.
you also need to actually execute the query:
$result = $qb->getQuery()->execute();
that should give you the results.
where('f.id IS NULL');
is wrong.
It should be
where('c.flag IS NULL');
Thanks for the help.
Both answers are correct. Heres the final code, in case someone else search.
Also, i had to replace the 'ON' with 'WITH'.
$available =
$qb
->select('f')
->from('Flag', 'f')
->leftJoin('Countries', 'c', 'WITH', 'c.flag = f.id')
->where('c.flag IS NULL');
$flags = $qb->getQuery()->execute();

Symfony One-To-Many, unidirectional with Join Table query

I have some One-To-Many, unidirectional with Join Table relationships in a Symfony App which I need to query and I can't figure out how to do that in DQL or Query Builder.
The Like entity doesn't have a comments property itself because it can be owned by a lot of different types of entities.
Basically I would need to translate something like this:
SELECT likes
FROM AppBundle:Standard\Like likes
INNER JOIN comment_like ON comment_like.like_id = likes.id
INNER JOIN comments ON comment_like.comment_id = comments.id
WHERE likes.created_by = :user_id
AND likes.active = 1
AND comments.id = :comment_id
I've already tried this but the join output is incorrect, it selects any active Like regardless of its association with the given comment
$this->createQueryBuilder('l')
->select('l')
->innerJoin('AppBundle:Standard\Comment', 'c')
->where('l.owner = :user')
->andWhere('c = :comment')
->andWhere('l.active = 1')
->setParameter('user', $user)
->setParameter('comment', $comment)
I see 2 options to resolve this:
Make relation bi-directional
Use SQL (native query) + ResultSetMapping.
For the last option, here is example of repository method (just checked that it works):
public function getLikes(Comment $comment, $user)
{
$sql = '
SELECT l.id, l.active, l.owner
FROM `like` l
INNER JOIN comment_like ON l.id = comment_like.like_id
WHERE comment_like.comment_id = :comment_id
AND l.active = 1
AND l.owner = :user_id
';
$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata(Like::class, 'l');
return $this->_em->createNativeQuery($sql, $rsm)
->setParameter('comment_id', $comment->getId())
->setParameter('user_id', $user)
->getResult();
}
PS: In case of Mysql, 'like' is reserved word. So, if one wants to have table with name 'like' - just surround name with backticks on definition:
* #ORM\Table(name="`like`")
I find the Symfony documentation very poor about unidirectional queries.
Anyway I got it working by using DQL and sub-select on the owning entity, which is certainly not as fast. Any suggestion on how to improve that is more than welcomed!
$em = $this->getEntityManager();
$query = $em->createQuery('
SELECT l
FROM AppBundle:Standard\Like l
WHERE l.id IN (
SELECT l2.id
FROM AppBundle:Standard\Comment c
JOIN c.likes l2
WHERE c = :comment
AND l2.owner = :user
AND l2.active = 1
)'
)
->setParameter('user', $user)
->setParameter('comment', $comment)
;

How to use doctrine QueryBuilder in a nested loop

I’m using QueryBuilder in the in the following way:
$qb = $entityManager->createQueryBuilder();
$qb->select('m')
->from('MyEntity', 'm');
$query = $qb->getQuery();
$collection = $query->getResult();
foreach ($collection as $item) {
$qb = $entityManager->createQueryBuilder();
$qb->update('MyEntity ', 'm')
->set('m.myItem', '?1');
$query = $qb->getQuery();
$result = $query->execute();
}
(I've remove a lot of details in order to focus on the gist of the question)
How should this script be written?
Is it appropriate to reuse $qb or should I use $qb1, $qb2,
etc.?
In this particular script, the results of the first instance of
QueryBuilder get passed into an array $collection before the next
steps, so I assume that I’m done with the first instance of
QueryBuilder at that time. Does there need to be something like
$qb->close before moving on?
Is it necessary to say $qb = $entityManager->createQueryBuilder();
more than once?