This is the current query that I have, and it works fine:
$q = $this->_em->createQuery("SELECT s FROM app\models\Sub s
LEFT JOIN s.case c
WHERE s.type LIKE '%$type'
AND c.id = '$id'");
foreach ($q->getResult() as $row) {
$results[$row->getId()] = $row;
}
I want to convert this to the QueryBuilder API structure, this is what I have so far, but it's not working correctly. (And I need the results as the same format as above).
$q = $this->_em->createQueryBuilder();
$q->add('select', 's')
->add('from', 'app\models\Sub s')
->add('leftJoin', 's.case c')
->add('where', 's.type LIKE :type')
->add('where', 'c.id = :case');
->setParameter('type', "%$type");
->setParameter('case', $id);
And again, this isn't working properly, and I don't know how to get the results in the same format as above. Thanks!
Close, but no cigar. You'll need to learn how to use the Expr classes that comes with Doctrine in order to create the correct WHERE clause.
http://www.doctrine-project.org/docs/orm/2.1/en/reference/query-builder.html#expr-classes
In the example you provided, you are actually aiming for something like this (not tested):
$q->add('select', 's')
->add('from', 'app\model\Sub s')
->add('leftJoin', 's.case c')
->add('where', $q->expr()->andX($q->expr()->like('s.type', ':type'), $q->expr()->eq('case', ':case')))
->setParameter('type', "%$type")
->setParameter('case', $id);
As your WHERE clause gets more complicated, so will the nesting of expressions.
Related
I have for example two tables: Parent and Children. They have relations many-to-many between each other. Everything is working well, but I don't know how to use where clause in query builder for this.
My code:
$parent = $em->getRepository('AppBundle:Parent')->find(1);
$qb = $em->createQueryBuilder();
$qb->select('c, p')
->from('AppBundle:Children', 'c')
->leftJoin('c.parents', 'p')
->where('p.id = :parent')
->setParameter('parent', $parent)
;
$childrens = $qb->getQuery()->getResult();
This always return me null.
I know - I can use $parent->getChildrens(), but I would like use createQueryBuilder for AppBundle:Children.
How should the where clause look?
i have the following code in my Entity Repository class:
$qb
->select('d')
->addOrderBy('d.dtrDate', 'DESC')
->where($qb->expr()->isNotNull('d.deletedAt'))
->leftJoin('d.user', 'u')
->where('u.id = :user_id')
->setParameter('user_id', $user->getId());
So basically, I dont want to select an entity where deletedAt property is not null. However it gives me a query like this:
>
SELECT
d0_.id AS id_0,
d0_.dtr_date AS dtr_date_1,
d0_.clock_in AS clock_in_2,
d0_.clock_out AS clock_out_3,
d0_.total_time AS total_time_4,
d0_.memo AS memo_5,
d0_.last_update_IP AS last_update_IP_6,
d0_.created_at AS created_at_7,
d0_.updated_at AS updated_at_8,
d0_.deleted_at AS deleted_at_9,
d0_.user_id AS user_id_10
FROM
daily_time_record d0_
LEFT JOIN user u1_ ON d0_.user_id = u1_.id
WHERE
u1_.id = ?
ORDER BY
d0_.dtr_date DESC
As you can see my first where is not being called. So how can i work on this?
You should read the documents, or read the ORM source to see how things work actually. TO be short, the answer to your question is:
$qb
->select('d')
->leftJoin('d.user', 'u')
->where($qb->expr()->isNotNull('d.deletedAt'))
->andWhere('u.id = :user_id')
->setParameter('user_id', $user->getId())
->orderBy('d.dtrDate', 'DESC');
I'm wondering what exactly are the pros of using doctrine to build queries such as :
<?php
// $qb instanceof QueryBuilder
$qb->select('u')
->from('User u')
->where('u.id = :identifier')
->orderBy('u.name ASC');
->setParameter('identifier', 100); // Sets :identifier to 100, and thus we will fetch a user with u.id = 100
The only advantage i see here is data sanitizing and parameter binding, which can be easily done using PDO.
Also another example :
<?php
// $qb instanceof QueryBuilder
// example8: QueryBuilder port of: "SELECT u FROM User u WHERE u.id = ? OR u.nickname LIKE ? ORDER BY u.surname DESC" using Expr class
$qb->add('select', new Expr\Select(array('u')))
->add('from', new Expr\From('User', 'u'))
->add('where', $qb->expr()->orX(
$qb->expr()->eq('u.id', '?1'),
$qb->expr()->like('u.nickname', '?2')
))
->add('orderBy', new Expr\OrderBy('u.name', 'ASC'));
Is it really worth the extra dependencies are performance cost ? The above syntax seems more complicated to me than a simple string containing the query.
It is more structural this way. It also removes DQL(or SQL) code from the PHP code that looks much better this way.
I'm using Doctrine 2.
I want to get all Entities of an entity class except for the one with id = 0.
I could use QueryBuilder like this:
// $em is EntityManager
$em->createQueryBuilder()
->select('c')
->from('Category', 'c')
->where('c.id <> 0')
->getQuery()
->getResult();
But looking at this code, it feels like too much for such a simple task.
I'm curious to know if there is any other simpler way in Doctrine for doing this.
Nop, that's how you should do it. You could omit query builder and pass entire DQL query:
$em->createQuery("SELECT c FROM Category c WHERE c.id != 0")->getResult();
It's not the better practice to pass the ID number, you might pass the Category object like this :
public function findAllExcept($category) {
$qb = $this->createQueryBuilder('Category');
$qb->add('select', 'c')
->add('from', 'Category c')
->add('where', 'c != :category')
->setParameter('category', $category);
return $qb->getQuery()->getResult();
}
For comparisons and conditions I recommend use Doctrine as well. It will save your time in case of switch between databases, for instance MySQL to PostgreSQL:
$this->createQueryBuilder()
->select('c')
->from('Category', 'c')
->where($qb->expr()->neq('c.id', '?1'))
->setParameter('1', $category)
->getQuery()
->getResult()
I'm trying to make a simple query with a subquery in a orWhere clause (with Doctrine).
As always, Doctrine tries to rename every aliases and completely destroys the queries...
Here's an example:
$q = Doctrine_Query::create()
->from('Actualite a')
->where('a.categorie_id =?', $id)
->orWhere('a.categorie_id IN (select id from cat.categorie as cat where cat.categorie_id =?)', $id)
->execute();
Which in MySQL would make something like:
SELECT *
FROM actualite a
WHERE a.categorie_id = 1 OR a.categorie_id IN (SELECT cat.id FROM categorie cat WHERE cat.categorie_id = 1);
Everything is right about it, but then again Doctrine destroys it:
Couldn't find class cat
Every time I try to do something a little complex with Doctrine, I have errors with aliases. Any advice or ideas about how to fix this?
Thanks!
The SQL example you've provided is fine but the corresponding Doctrine syntax has a couple of errors. Here's a clean version:
$q = Doctrine_Query::create()
->select('a.*')
->from('Actualite a')
->where('a.categorie_id = ?', $id)
->orWhere('a.categorie_id IN (SELECT cat.id FROM Categorie cat WHERE cat.categorie_id = ?)', $id)
->execute();
You should use createSubquery() to explicitely tell doctrine about your nested subquery. So your query should look something like this:
$q = Doctrine_Query::create()
->select('a.*')
->from('Actualite a')
->where('a.categorie_id = ?', $id)
;
$subquery = $q->createSubquery()
->select("cat.id")
->from("Categorie cat")
->where("cat.categorie_id = ?", $id)
;
$q->orWhere('a.categorie_id IN ('.$subquery->getDql().')')->execute();
Another example can be found here:
http://www.philipphoffmann.de/2012/08/taming-doctrine-subqueries/
I think you query should be like this add the select and remove as
$q = Doctrine_Query::create()
->select('a.id')
->from('Actualite a')
->where('a.categorie_id =?', $id)
->orWhere('a.categorie_id IN (select id from cat.categorie cat where cat.categorie_id =?)', $id)
->execute();
Try this may help you.
Thanks