doctrine2 order by array with ids - symfony

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

Related

Method findBy() from Doctrine with DateTime

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.

Symfony2 - Query Builder multiple orderBy

I have the following code
public function queryAssociationsSorted($id){
$qb = $this->createQueryBuilder('a')
->leftJoin('a.category', 'c')
->where('a.job = :id')
->setParameter('id', $id)
//->addOrderBy('c.rank', 'DESC')
//->addOrderBy('a.updated', 'DESC')
->add('orderBy','c.rank DESC THEN a.updated DESC')
;
return $query = $qb->getQuery();
}
and this or the commented out options both only sort by a.updated. I have looked at other posts on this subject and can't find a solution. Can anyone suggest where I am going wrong?
If I understand correctly, and this is the result yu want:
id - rank - updated
xx - 4 - 2014-01-01
xx - 3 - 2014-01-02
xx - 3 - 2014-01-01
This actually works:
$qb = $this->createQueryBuilder('a')
->leftJoin('a.category', 'c')
->where('a.job = :id')
->setParameter('id', $id)
->addOrderBy('c.rank', 'DESC')
->addOrderBy('a.updated', 'DESC')
;
return $query = $qb->getQuery();
I'm not sure how doctrine works with multiple sort by..
why dont you try to use dql or even raw sql query?
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html
http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html
Edit:
something like that will work I think:
->add('orderBy','c.rank DESC, a.updated DESC')
If you still have no success the raw sql query will save you ;)
Over a year later and I've stumbled across the correct answer in this answer by #red777
This will help you:
$adapter = new DoctrineORMAdapter($queryBuilder, false);
Had the same problem this morning. By default Pagerfanta is treating your query as
one with joins. Setting second argument to false makes it use simple
query handling.
In Kunstmaan Bundle, in AdminListConfiguration class, you have to
overide function that is creating Pagerfanta, if you want to sort
simple entity.
The syntax in the query had always been correct, but the error crept in in the DoctrineOrmAdapter. Adding false as the second parameter sorted the problem

Delete function using join in DQL

I'm trying to use the Doctrine QueryBuilder to perform the Delete function using query
I need to delete a record that is present in 2 tables ,
in TcTracks table the id is "id" and in TcWall teh id is "related_id"
my controller
public function deleteAction(Request $request){
$deleteQuery = $this->getDoctrine()
->getManager()
->createQueryBuilder('d')
->delete('TcPlayerBundle:TcTracks', 'd')
->innerJoin('TcprofileBundle:TcWall', 't', 'ON', 'd.id = t.related_id')
->where('d.id = :dId')
->setParameter('wId', $request->get('related_id'))
->setParameter('dId', $request->get('id'))
->getQuery();
$deleted = $deleteQuery->getResult();
$deleted->flush();
return $this->render('TcPlayerBundle:Default:all.html.twig',array(
'tracks' => $tracks
));
}
i need to delete same record in two tables , but its not performing for both tables, kindly help me
i'm getting error as
Invalid parameter number: number of bound variables does not match number of tokens
Remove the line below:
->setParameter('wId', $request->get('related_id'))
There is only :dId but no :wId.
Actually you did inner join by 'd.id = t.related_id', so related_id is not necessary to set any more.
You don't have wID parameter anywhere in query. In the same time you're using ->setParameter('wId', $request->get('related_id')) which is obsolete in this case. Try to remove this row and it should be fine.
Is one-to-many realation with your entities
TcPlayerBundle:TcTracks
and
TcprofileBundle:TcWall
if like that,you can do some like:
oneToMany:
cascade: [remove]
in your config 'yourentity.orm.yml' file..
hope hlep you!

Symfony2 Select one column in doctrine

I'm trying to refine the query trying to select fewer possible values ​​..
For example I have an entity "Anagrafic" that contains your name, address, city, etc.,
and a form where I want to change only one of these fields, such as address.
I have created this query:
//AnagraficRepository
public function findAddress($Id)
{
$qb = $this->createQueryBuilder('r')
->select('r.address')
->where('r.id = :id')
->setParameter('id', $Id)
->getQuery();
return $qb->getResult();
}
there is something wrong with this query because I do not return any value, but if I do the query normally:
//Controller
$entity = $em->getRepository('MyBusinessBundle:Anagrafic')->find($id);
Return the right value.
How do I do a query selecting only one column?
Since you are requesting single column of each record you are bound to expect an array. That being said you should replace getResult with getArrayResult() because you can't enforce object hydration:
$data = $qb->getArrayResult();
Now, you have structure:
$data[0]['address']
$data[1]['address']
....
Hope this helps.
As for the discussion about performance in comments I generally agree with you for not wanting all 30 column fetch every time. However, in that case, you should consider writing named queries in order to minimize impact if you database ever gets altered.
You can use partial objects to only hydrate one field and still return a object.
This worked for me:
$qb = $repository->createQueryBuilder('i')
->select('i.name')
->...
Use partial objects like this to select fields
$qb = $this->createQueryBuilder('r')
->select(array('partial r.{id,address}'))
...
Put your field names between the brackets

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