How convert SQL query to Doctrine2? - php

I want to convert this in Doctrine2.
Similar to these questions:
Symfony2 / Doctrine2 - How to convert this SQL request with QueryBuilder?
How to convert a complex MySQL Query to Doctrine2
Convert SQL to Doctrine 2 Query Builder or DQL by using NOT IN?
Is it possible?
SELECT
SUM(q.amount)
FROM(
SELECT amount
FROM expense_report e0_
WHERE
(e0_.is_account_transfer = 0)
AND (e0_.remove_date IS NULL)
LIMIT 0, 2) q
Thanks

you can archive your problem with this custom repository method:
public function getAmount()
{
$qb = $this->createQueryBuilder("q");
return
$qb
->select("sum(q.amount)")
->where($qb->expr()->isNull('q.remove_date'))
->andWhere('q.is_account_transfer = 0')
->setFirstResult(0)
->setMaxResults(2)
->getQuery()
->getSingleScalarResult();
}
And simply use it, as example, in a controller method as:
public function testAction()
{
....
$totalAmount = $this->getDoctrine()
->getRepository("AcmeDemoBundle:ExpenseReport")
->getAmount();
...
}
Hope this help

Related

Parameters not being replaced in Doctrine

I am unable to figure what is the problem here.
I have created the below query using doctrine Query Builder
$repo = $this->em->getRepository(self::STORE_TIMING);
$qb = $repo->createQueryBuilder('store_timings');
$qb->select('st')
->where('st.id = :identifier')
->setParameter('identifier', 100);
When i print the DQL :
print_r($qb->getDQL());die();
The query that is output is :
SELECT st FROM Test\BotBundle\Entity\StoreTimings store_timings WHERE st.id = :identifier
To my surprise the :identifier is not being replaced.
Request for some guidelines here.
If you are using getDQL It doesn't return the query with parameter.
I advise you to use the _profiler to view the complete query with parameter

Doctrine 2 simple "bigger than" criteria

In PDO / SQL i have a simple query with "bigger than":
DELETE * FROM tablexyz WHERE access > :old
Whats the equivalent in Doctrine 2 ORM?
I have already written a little code:
$criteria = ['access'=>$old];
$dataRepo = $entityManager->getRepository('tablexyz')->findBy($criteria)->delete();
My problem is, i want to use the bigger than operator in Doctrine 2 ORM but i don't want to make a function or class for that. Does somebody know a better or shorter solution for that?
You can use either a query builder og just do a direct DQL (or SQL) query for it.
$qb = $entityManager->createQueryBuilder();
$qb->select('e')
->from('Entityxyz', 'e')
->where('e.access > :old')
->setParameter('old', $old);
$entities = $qb->getQuery()->getResult();
or
$query = 'SELECT e FROM AppBundle\Entity\Entityxyz WHERE e.access > :old';
$entities = $entityManager->createQuery($query)
->setParameter('old', $old)
->getResult();`
I'd suggest you do create a repository method for it though, it's the correct place to have it. Using the query builder inside the repository is also simpler as it knows which entity you're referencing (and can skip calling select and from)
class EntityxyzRepository extends EntityRepository
{
public function getNewerThan($newerThan)
{
$qb = $this->createQueryBuilder('e');
$qb->where('e.access > :newerThan')
->setParameter('newerThan', $newerThan);
return $qb->getQuery()->getResult();
}
}

Symfony Doctrine disable cache

In my symfony project I have two entities that are related via one to many.
I need to find the first and last child, so I use repository functions that look like this:
public function getFirstPost(Topic $topic)
{
$query = $this->createQueryBuilder('t')
->addSelect('p')
->join('t.posts', 'p')
->where('t.id = :topic_id')
->setParameter('topic_id' => $topic->getId())
->orderBy('p.id', 'ASC')
->setMaxResults(1)
->getQuery();
return $query->getOneOrNullResult();
}
public function getLastPost(Topic $topic)
{
$query = $this->createQueryBuilder('t')
->addSelect('p')
->join('t.posts', 'p')
->where('t.id = :topic_id')
->setParameter('topic_id' => $topic->getId())
->orderBy('p.id', 'DESC')
->setMaxResults(1)
->getQuery();
return $query->getOneOrNullResult();
}
So the only difference is in in ->orderBy(), for the first Post I use ASC and for the last I use DESC.
Now If I use one of those functions from my controller, the return the expected result and work just fine. But If I run them both at the same time from my controller, they return the same result, which they shouldn't.
My guess is that Doctrine caches these queries and the results somehow and that's why the return the same so I tried using $query->useResultCache(false) but that didn't do anything.
So my question is, why is this happening and how can I fix it?
Well, it is cache issue indeed, but mostly it is query issue. Instead of returning a post in these function you return the whole topic with joined posts.
What you can do is to rewrite these queries to select Post entity directly and join Topic entity to it which will be filtered by.
If you really(dont do this) need these queries to work you can detach first topic returned by one of those methods and then call the other method:
$this->getDoctrine()->getManager()->detach($firstTopic);

doctrine not exists subquery

I have in a repository this code:
public function getNotAssignedBy($speciality, $diploma)
{
$qb = $this->createQueryBuilder('j')
->select('DISTINCT(j.id) id', 'j.firstName', 'j.lastName', 'j.dateBirth', 'j.sex')
->leftJoin('j.qualifications', 'q')
;
if ($speciality) {
$qb->andWhere('q.speciality = :speciality_id')->setParameter('speciality_id', $speciality);
}
if ($diploma) {
$qb->andWhere('q.diploma = :diploma_id')->setParameter('diploma_id', $diploma);
}
$result = $qb->getQuery()->getResult();
return $result;
}
How can I get only rows where id not exists in another entity ??
Any help. Thanks
You can achieve it with something like this:
....
// construct a subselect joined with an entity that have a relation with the first table as example user
$sub = $this->createQueryBuilder();
$sub->select("t");
$sub->from("AnotherEntity","t");
$sub->andWhere('t.user = j.id');
// Your query builder:
$qb->andWhere($qb->expr()->not($qb->expr()->exists($sub->getDQL())));
Hope this help
Since I can't comment, so I will post a fixed version of #Matteo's solution
The correct way to use createQueryBuilder in this case is by using EntityManager. See my comment in the code below.
$sub = $this->_em->createQueryBuilder(); // _em stands for entity manager here. While $qb may use repositories createQueryBuilder() which requires alias
$sub->select("t");
$sub->from("AnotherEntity","t");
$sub->andWhere('t.user = j.id');
// Your query builder:
$qb->andWhere($qb->expr()->not($qb->expr()->exists($sub->getDQL())));

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