Doctrine2 empty parameter on queryBuilder - symfony

I am trying to check whether an user email is set or not. I am able to get the ones that are set to NULL but I am missing on the ones that have an empty string as the value. Here is my attempt:
$user = $this->createQueryBuilder('u')
->where('(u.email IS NULL OR u.email = :empty)')
->setParameter('empty', "''")
->getQuery()->getResult()
;
I have no problem getting the NULL emails but I fail to get the empty string emails. Is there any way to accomplish this or is it not supported in DQL?

How about this (EDIT #2):
$user = $this->createQueryBuilder('u')
->where('u.email = NULL')
->orWhere('u.email = \'\'')
->getQuery()->getResult()
;
Does that work?

Worths mention that the Expr Helper from QueryBuilder provides a function for that:
// Example - $qb->expr()->isNull('u.id') => u.id IS NULL
public function isNull($x); // Returns string
So for your case you can do something like:
$qb = $this->createQueryBuilder('u');
$qb
->where(
$qb->expr()->orX(
$qb->expr()->isNull('u.email'),
$qb->expr()->eq('u.email', ':empty'),
)
)
->setParameter('empty', '""');
$users = $qb->getQuery()->getResult();

Related

DQL query ManyToMany IN

This query in not working. What could be wrong? Post has author(User entity). User has Following(ManyToMany self-directing)
I'm trying to get all Posts of the Users which I'm following
$userId = $this->getUser()->getId();
$qb = $em->createQueryBuilder();
$qb2 = $qb;
$qb2 = $em->createQueryBuilder()
->select('u.following')
->from('AppBundle\Entity\User', 'u')
->where('u.id = :userId');
$qb->select('p')
->from('AppBundle\Entity\Post', 'p')
->where($qb->expr()->In('p.author', $qb2->getDQL()));
$qb->setParameter('userId', $userId);
$dql = $qb->getDQL();
I will assume that your code is in repository as it should be...
src/AppBundle/Controller/PostController.php
$em=$this->getDoctrine()->getManager();
$myResultCollection=$em->getRepository(Post::class)->myCustomQuery($this->getUser());
src/AppBundle/Repository/PostRepository.php
public function myCustomQuery(User $user) {
$em=$this->getEntityManager();
$qb=$em->createQueryBuilder();
return $qb->select("p")
->from(Post::class, "p")
->where($qb->expr()->in("p.author",
$qb->select("u.following")
->from(User::class, "u")
->where("u.id=:USERID")
->getDQL()))
->setParameters(array('USERID'=>$user->getId()))
->getQuery()
->execute();
}
As side note, you should be careful with quotes.
Make sure to use double quotes when using DQL (it's true for SQL too).
The reason is because you need simple quote for strings in queries.

How to get previous and next entity through entity manager

This is how i'm able to fetch an user entity using it's id:
$userEntity = $em->getRepository('ModelBundle:User')->find($userId);
Is there a way to get previous and next entity based on this $userEntity?
For example: i fetched $userEntity and it's id is 100, now i want fetch previous entity irrespective to its id 99, 80, 70 whatever it is! same with case with next entity..
I can already fetch next and previous using some PHP hack, however i'm looking for better approach..
Edited:
Just to clarify i'm looking for object oriented approach, something like below:
$userEntity = $em->getRepository('ModelBundle:User')->find($userId);
$previousUserEntity = $userEntity->previous(); //example
$previousUserEntity = $userEntity->next(); //example
I know userEntity does't contain any method like previous() and next(), it's just an example, if anything like that exist which can help directly get next and previous entities in object oriented fashion!
Add this funstion to your repository class
public function previous(User $user)
{
return $this->getEntityManager()
->createQuery(
'SELECT u
FROM ModelBundle:User u
WHERE u.id = (SELECT MAX(us.id) FROM ModelBundle:User us WHERE us.id < :id )'
)
->setParameter(':id', $user->getId())
->getOneOrNullResult();
}
public function next(User $user)
{
return $this->getEntityManager()
->createQuery(
'SELECT u
FROM ModelBundle:User u
WHERE u.id = (SELECT MIN(us.id) FROM ModelBundle:User us WHERE us.id > :id )'
)
->setParameter(':id', $user->getId())
->getOneOrNullResult();
}
It's possible to get the previous and next records by searching for all the records with a value greater or less than a given value, sort them and then take only the first or last result.
Let's say we have these ids:
70
80
99
100
In order to get the user before 99, we want the last user which id is less than 99. Here is the code for adding this in a custom repository:
public function getPreviousUser($userId)
{
$qb = $this->createQueryBuilder('u')
->select('u')
// Filter users.
->where('u.id < :userId')
->setParameter(':userId', $userId)
// Order by id.
->orderBy('u.id', 'DESC')
// Get the first record.
->setFirstResult(0)
->setMaxResults(1)
;
$result = $qb->getQuery()->getOneOrNullResult();
}
And in the controller:
$em->getRepository('ModelBundle:User')->getPreviousUser($userId);
This will return the record with id 80.
In order to get the user after 99, we want the first user which id is greater than 99:
public function getNextUser($userId)
{
$qb = $this->createQueryBuilder('u')
->select('u')
->where('u.id > :userId')
->setParameter(':userId', $userId)
->orderBy('u.id', 'ASC')
->setFirstResult(0)
->setMaxResults(1)
;
$result = $qb->getQuery()->getOneOrNullResult();
}
And in the controller:
$em->getRepository('ModelBundle:User')->getNextUser($userId);
This will return the record with id 100.

'Invalid parameter number: number of bound variables does not match number of tokens' Symfony

I'm working on a symfony project entity with query builder. When I try to run this function I get this issue.
Invalid parameter number: number of bound variables does not match number of tokens
public function json_filterAllproductsAction() {
$search = "";
$category = 1;
//Combine tables and create the query with querybuilder
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p')
->from('EagleAdminBundle:Products', 'p')
->orderBy('p.id', 'DESC');
if ($category != 0) {
$qb->where($qb->expr()->in('p.category', '?1'))
->setParameter(1, $category);
}
$qb->where('p.productTitle LIKE :title')
->setParameter('title', "$search%");
//convert to json using "JMSSerializerBundle"
$serializer = $this->container->get('serializer');
$jsonproducts = $serializer->serialize($qb->getQuery()->getResult(), 'json');
return new Response($jsonproducts);
}
I think error is in
$qb->where($qb->expr()->in('p.category', '?1'))
->setParameter(1, $category);
It would be great help someone can help me.
You have two issues here. The first is that your last where clause overwrites the first one. This can be fixed by using andWhere. The second is that your mixing named parameters (:title) with positional parameters (?1). Mixing is a no no. And you don't really need the expr object. Try:
$qb->select('product')
->from('EagleAdminBundle:Products', 'product')
->orderBy('product.id', 'DESC');
if ($category) {
$qb->andWhere('product.category IN (:category)');
$qb->setParameter('category', $category);
}
$qb->andWhere('product.productTitle LIKE :title');
$qb->setParameter('title', "$search%");

symfony doctrine find User by Email

ok, with
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->find($user_id)
I get an User by the given Identifier (ID).
but how can I get him by given email?
$emailCheck = $em->createQueryBuilder('u')
->select('u, r')
->where('u.email = :email')
->setParameter('email','test#email.com')
->getQuery();
Whill it return an array or an object? Is this the right way to handle it?
This will return a User object.
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findOneByEmail($email);
You can use either
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findBy(array('email' => $email));
To load an array of User entities. (Will always be a list, even with 0 or 1 results.)
Or you can do:
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findOneBy(array('email' => $email));
This will return the first found result as a User entity object.
You can use the getOneOrNullResult(), as well, it's the long variant. Note however that you should always use setMaxResults(1) with this, otherwise you'll get an exception if more than one result is found (SF 2.3.x).
Either you use the magic method of Doctrine findOneByyour_field or you can create your own method in your repo
public function findOneByEmailAndStoreId($email, $store_id)
{
$q = $this->createQueryBuilder('c')
->where('c.email = :email')
->andWhere('c.store_id = :store_id')
->setParameter('email', $email)
->setParameter('store_id', $store_id)
->getQuery();
return $q->getOneOrNullResult(); // will return only one result or null 'getResult' will return a collection
}

Use Limit and Offset in Doctrine2 query

I'm trying to do the pagination, but there is an error:
[Syntax Error] line 0, col 57: Error: Expected end of string, got 'limit'
I'm not quite sure if this is the right syntax (and logic) to make my query:
public function getFriendsFromTo ($user, $limit, $offset)
{
return $this->getEntityManager()
->createQuery('SELECT f FROM EMMyFriendsBundle:Friend f WHERE f.user='.$user.' limit '.$limit. 'offset' .$offset)
->getResult();
}
Friends and users are related manyToOne and oneToMany, so in the friends table there is a field - user_id.
This is in my controller:
$user = $this->get('security.context')->getToken()->getUser();
$id = $user->getId();
$friends = $user->getFriends();
$result = count($friends)
$FR_PER_PAGE = 7;
$pages = $result/$FR_PER_PAGE;
$em = $this->getDoctrine()->getEntityManager();
$friends = $em->getRepository('EMMyFriendsBundle:Friend')
->getFriendsFromTo($id, $FR_PER_PAGE, $page*$FR_PER_PAGE);
I know that it's stupid and even wrong (especially the third parameter to be $page*$FR_PER_PAGE), but I just wanted to try if the query works, and it didn't.
Nope. Use:
return $this->getEntityManager()
->createQuery('...')
->setMaxResults(5)
->setFirstResult(10)
->getResult();
$towary = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Towar')
->findBy(array(),array(),10,($current-1)*$numItemsPerPage);
You can use findBy 3rd and 4th parameters of method of doctrine repository, which are limit and offset.
Here is the method definition:
findBy(
array $criteria,
array $orderBy = null,
integer|null $limit = null,
integer|null $offset = null
)
Source: http://www.doctrine-project.org/api/orm/2.2/class-Doctrine.ORM.EntityRepository.html
you can also use
$query->getSingleResult();
Doctrine2.6, stumbled upon this old post and tried the DQL way but it did not fit for purpose. So if you want to avoid using DQL because you already have Entities mapped and joined together, you can do paging using matching & Criteria
$criteria = Criteria::create()
->setMaxResults($limit ? $limit : null)
->setFirstResult($offset ? $offset : null)
$result = $em->getRepository('EMMyFriendsBundle:Friend')
->matching($criteria)->toArray();

Resources