Method findBy() from Doctrine with DateTime - symfony

I have the following code, but this would not work:
$event= $this->getDoctrine()
->getRepository('AppBundle:Event')
->findBy(
array(
"datestart" => array(new \DateTime())
)
);
I need a list of the events, which are newer then now.
Where is my misstake?
Or isn't that able to get with the default findBy() function of doctrine ?

findBy only search for exactly matches while you need greater then. In this case and also many other cases you can write your own query. You could use DQL or the queryBuilder. If you want to be able to re-use your query on other places then you could place your query in a repository class which is a good practice too. (check the docs). Now here you find a DQL example that you can place into your controller:
$events = $this->getDoctrine()
->getManager()
->createQuery('SELECT e FROM AppBundle:Event e WHERE e.datestart > CURRENT_DATE()')
->getResult();
i changed your variabele to $events (with s) because you are expecting possible more than one event.

Related

Symfony2 simple query: can't fetch an object, only array

The following query in Symfony2.6 works with getArrayResult(); BUT doesn't work with getResult(); or getOneOrNullResult();. This means that I can't fetch an object but only an array.
If I use this query, all I get is a white/blank page (not even the symfony debug toolbar). Note that in my twig template I just do a {{ dump() }} of the query result.
The table structure is easy (it's a list of books read by the users):
id, user, book, status, vote, review
(user, book and status are foreign keys)
public function selectOneRecordBy2Ids($user_id, $book_id)
{
/* #var $qb QueryBuilder */
$qb = $this->createQueryBuilder('l');
$qb->select('l');
$qb = $qb->Where($qb->expr()->eq('l.user', ':first'));
$qb = $qb->andWhere($qb->expr()->eq('l.book', ':second'));
$qb = $qb->setParameters(array('first' => $user_id, 'second' => $book_id));
return $qb->getQuery()->getOneOrNullResult();
}
I've noticed a few bad practices here, so let me correct them:
public function selectOneRecordBy2Ids(User $user, Book $book)
{
/* #var $qb QueryBuilder */
$qb = $this->createQueryBuilder('l');
$qb
->andWhere($qb->expr()->eq('l.user', ':first'))
->andWhere($qb->expr()->eq('l.book', ':second'))
->setParameters(array('first' => $user, 'second' => $book));
return $qb->getQuery()->getResult();
}
Select is not necessary if you work only with one entity and you don't fetch any relations. QB returns $this so you can chain the method calls.
Try to use entities as parameters instead of primitive types (if it is possible). If not, then you have to use primitive types as primitives in QB. In this case you'll need a few joins:
->select('l')
->join('l.user', 'u')
->join('l.book', 'b')
->andWhere($qb->expr()->eq('u.id', ':first'))
->andWhere($qb->expr()->eq('b.id', ':second'))
->setParameters(array('first' => $user_id, 'second' => $book_id));
If you want to fetch only one record, then you may have to limit the results by setting the max results:
->setMaxResults(1)
I hope this helps and solves your original problem as well.
getOneOrNullResult() does not return the record, but tells you if any record in database is found, or not.
You might want to use getSingleResult()

doctrine query onetonmany / notIn with objects / symfony forms querybuilder

I am using symfony 2 and doctrine to prefilter a form field type 'entity' with the help of a querybuilder.
My querybuilder should return all products which the user has not already added to a list.
All relations are bidirectionnal.
I have products linked to userIngredients (oneToMany) each linked to one user (manyToOne)
I have come with this so far but it's not working, I get products not added by other users.
return $this
->createQueryBuilder('p')
->leftJoin('p.userIngredients', 'i')
->where('i.user <> ?1')
->setParameter(1,$user);
1; Any clue on how to correct this ?
Alternatively, I could select the products I don't want and then reselect those who don't match but using an expression and NotIn seems to only work for strings
$products = $this
->createQueryBuilder('p')
->leftJoin('p.userIngredients', 'i')
->where('i.user = ?1')
->setParameter(1,$user)
->getQuery()
->getResult();
return $this
->createQueryBuilder('p')
->where($this->createQueryBuilder('p')->expr()->notIn('p', $products));
2; how could we correct this to make it work with objects ?
3; alternatively : is there a way to pass not a querybuilder but an array of results to symfony form builders ?
I got thinks thanks to Javad:
(slight modification, I'm using an array result, not dql):
$qb = $this->_em->createQueryBuilder();
$ids = $qb
->select('p.id')
->from('AppBundle:MarketPlace\Product','p','p.id')
->leftJoin('p.userIngredients', 'i')
->where('i.user = ?1')
->setParameter(1,$user)
->getQuery()
->getResult();
//I don't know why I couldn't directly get an array of ids otherwise... if you know how to do better directly from the query, I'm interested (getScalarResult does not make it)
$ids=array_keys($ids);
$result = $this
->createQueryBuilder('p')
->where($this->createQueryBuilder('p')->expr()->notIn('p.id', $ids));
return $result;

doctrine2 order by array with ids

How I can with doctrine2 order by array with ids ?
I have this query:
$qb = $this->createQueryBuilder('u')
->select('u', 'n', 'c')
->leftJoin('u.notifications', 'n')
->leftJoin('u.channel', 'c')
->andWhere('u.id IN (:ids)')
->setParameter('ids', $ids);
I want that the result has the same order that array with ids, is possible do it ?
Thanks
SOLUTION:
Use FIELD mysql extension with https://github.com/beberlei/DoctrineExtensions
:)
Thanks
Simple solution that doesn't require presorting query result:
$idPositions = array_flip($userIds); // Mapping of id to position
usort($users, function($userA, $userB) use ($idPositions) {
return $idPositions[$userA->id] - $idPositions[$userB->id];
});
If you are using MySQL, sorting with the FIELD() function could accomplish this. DQL doesn't have built-in support for this function, so you'll either have to create a user defined function (see this answer), or create a native query.
I have a solution that is probably very inefficient, but it works. Make sure your results are ordered by id.
$users = $entityManager
->getRepository('User')
->findById($userIds, ['id' => 'ASC']);
$userIdsCopy = $userIds;
sort($userIdsCopy);
array_multisort($userIds, $userIdsCopy);
array_multisort($userIdsCopy, $users);
It's hard to explain how this works, but basically you "remember" the operations that happen when you sort the userId-array, then you apply the opposite of that to the query result.
I found the solution, it is possible using FIELD mysql extension with https://github.com/beberlei/DoctrineExtensions
Thanks
Marc
Which id do you want to order by?
You can use...
->orderBy('u.id', 'asc')
// or n.id
// or c.id
Or you can use multiple order by's ("by's" doesn't seem right to me)...
->addOrderBy('u.id', 'asc')
->addOrderBy('u.name', 'desc') // if it exists

Symfony/Doctrine: fetching data as object , still get array

I have in my controller $id it's a foreign key
$query = $em->getRepository('SurgeryPatientBundle:Patients')->findPatientByUserID($id);
And in my repository file this function
public function findPatientByUserID($id)
{
return $this->getEntityManager()
->createQuery('SELECT p FROM SurgeryPatientBundle:Patients p WHERE p.user ='.$id.'')
->execute();
}
I want get an instance of object but still get an array. Query with find($id) works good
edit
Problem solves , I'm so stupid , I had invoked to $query[0]
You can use $query->getSingleResult(); as well
see here
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html#query-result-formats
If you want to grab the object, you shouldn't be using DQL. Doctrine entities have a find function that takes care of this for you.
Instead of all that code, you can just use (in your controller):
$em->getRepository('SurgeryPatientBundle:Patients')->find($id);
DQL is very powerful, but for simple lookups like this using the built in find methods will be more efficient & provide the entities as doctrine objects.

How to list user based on their roles in Symfony2 + Doctrine effectively

I have done this with this code
$users = $this->getDoctrine()->getEntityManager()
->createQuery('SELECT tu FROM UserBundle:User tu')
->getResult();
$result = array();
foreach($users as $user){
if($user->hasRole('ROLE_CUSTOMER'))
$result[] = $user;
}
return $this->render('XBundle:Order:index.html.twig',
array('users' => $result));
But what is the simple way to achieve this same result ?
Thanks.
Update, additional info:
Our main problem is that user roles have a hierarchical structure.
So ROLE_EDITOR will automatically have ROLE_WRITER if I defined ROLE_WRITER under ROLE_EDITOR.
Thus I can't just use simple query, I think I also have to utilize security context component.
I don't know your schema, but I guess you could do an INNER JOIN and put your condition in the ON clause. Read this article about the query builder to figure out how to build your query.
Doctrine collections also have a filter method that takes a Closure as an argument.

Resources