How To Build Query with QueryBuilder? - php

I'm currently trying to build a query with the Doctrine2 QueryBuilder. However, I am stuck when trying to do the following:
I have an entity called 'Customer'. This entity stands in a ManyToMany-Relation to 'User'. 'User' again stands in a ManyToMany-Relation to PhoneNumber.
So it's pretty much:
Customer <- #ManyToMany -> User <- #ManyToMany -> PhoneNumber
Now I am trying to select a customer based on a PhoneNumber. So right now I have the following:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('c')
->from('AppBundle:Customer', 'c')
->join('AppBundle:User', 'u')
->join('AppBundle:PhoneNumber', 'u');
Problem now is that I don't know on how to build the where-section of the query. Reason is that there can be several users and several phone numbers bound to the customer. Do you have an idea on how to proceed?

If you have entities with mappedBy / InversedBy you can do
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('c')
->from('AppBundle:Customer', 'c')
->innerJoin('c.users', 'u')
->innerJoin('u.phoneNumbers', 'p')
->andWhere('p.number = :numberPhone')
->setParameter('numberPhone', $varPhoneNumber)
;

My solution:
Using innerJoin() and 'MEMBER OF' fixed the problem. This way I can connect every entity with any other entity. E.g:
$qb = $this->getEntitiyManager()->createQueryBuilder()
->select('c')
->from('AppBundle:Customer', 'c')
->innerJoin('AppBundle:User', 'u', 'WITH', 'c.id MEMBER OF c.users')
->innerJoin('AppBundle:PhoneNumber', 'ph', 'WITH', 'ph.id MEMBER OF u.phoneNumbers')
->orWhere($qb->expr()->orX(
$qb->expr()->eq('ph.number', ':number')
))
->setParameter('number', $somePhoneNumber);

Related

How to make a join query on Symfony with Doctrine?

I'm kinda stuck on using the querybuilder to create a join query.
There is a table called "Person" and a table called "Vacancy". If a person is linked to the vacancy the person.id and vacancy.id is saved in a table called "Candidacy". So how do I get all the persons who are linke to vacancy.id 1?
So where do I have to initiate the AppBundle:Candidacy entity?
$entity = $em
->getRepository('AppBundle:Person')
->createQueryBuilder('p')
->join('p.id', 'c')
->where('c.vacancyId= 1')
->getQuery()
->getResult();
Thank you in advance.
Example in your repository :
public function getPersonVacancy($personId) {
$qb = $this->createQueryBuilder('p');
$qb->leftJoin('p.vacancy', 'v');
$qb->select('v.name', 'v.id');
$qb->where('p.id = :personId');
$qb->setParameter('personId', $personId);
return $qb ->getQuery()->getResult();
This is to give you an example it may not work with copy paste.
Also, all join methods are explained in doctrine documentation, feel free to read it http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html
Looks like you have many-to-many relation.
You should link your Person and Vacancy table through Candidacy to Person and then Vacancy to Candidacy.
small example: Entity User is attached to Engagement via UserEngagement table.
$qb = $this->_em->createQueryBuilder()
->select('u')
->from($this->_entityName, 'u')
->join('u.userEngagements', 'ue')
->join('ue.engagement', 'en')
...

Extra Where when using Join in Doctrine Query Language

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');

Doctrine2 get object without relations

An user has one role.
A role has zero or many users.
I would like to find roles without users.
I need to have this query without using IN or NOT IN
I tried with join:
$qb = $this->createQueryBuilder('role');
$qb
->leftJoin('role.users', 'users')
->where('users IS NULL')
without join
$qb = $this->createQueryBuilder('role');
$qb
->where('role.users IS NULL')
with id:
$qb = $this->createQueryBuilder('role');
$qb
->leftJoin('role.users', 'users')
->where('users.role != role')
Do you have other ideas? Do I have no other choices than to use IN / NOT IN queries?
Thanks in advance
You can find roles that don't have any users by using a count query
$qb = $this->createQueryBuilder('role');
$qb ->addSelect('COUNT(users.id) AS total_users')
->leftJoin('role.users', 'users')
->groupBy('role.id')
->having('total_users = 0')
->getQuery()->getResult();

DQL Allow Nullable Join?

In my entity 'Item', there is an ArrayCollection property known as "products" (of Entity 'Product') that can be empty
I need all product info (empty or not) in one DQL call for the array of 'Item' entities
$query = $this->getEntityManager()->createQueryBuilder();
$query->select(['v', 'p'])->from($this->getEntityName(), 'v')
->join('v.products', 'p')
->orderBy('v.datePublished', 'DESC')
->setMaxResults($limit);
The problem here, is that the only records that get returned are ones that have at least one product in them. I need to return Items that have empty products as well.
Any thoughts?
Ok, so.. this is all that needed to happen:
$query = $this->getEntityManager()->createQueryBuilder();
$query->select(['v', 'p'])->from($this->getEntityName(), 'v')
->join('v.products', 'p')
->orderBy('v.datePublished', 'DESC')
->setMaxResults($limit);
becomes
$query = $this->getEntityManager()->createQueryBuilder();
$query->select(['v', 'p'])->from($this->getEntityName(), 'v')
->leftJoin('v.products', 'p')
->orderBy('v.datePublished', 'DESC')
->setMaxResults($limit);
I'm excited to get back to my life now.

Doctrine 2 - Find all entities in a repository except one with a particular id value

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()

Categories