How to sort findAll Doctrine's method?
SymfonyDoctrine OrmSymfony Problem Overview
I've been reading Doctrine's documentation, but I haven't been able to find a way to sort findAll() Results.
I'm using symfony2 + doctrine, this is the statement that I'm using inside my Controller:
$this->getDoctrine()->getRepository('MyBundle:MyTable')->findAll();
but I want the results to be ordered by ascending usernames.
I've been trying to pass an array as an argument this way:
findAll( array('username' => 'ASC') );
but it doesn't work (it doesn't complain either).
Is there any way to do this without building a DQL query?
Symfony Solutions
Solution 1 - Symfony
As @Lighthart as shown, yes it's possible, although it adds significant fat to the controller and isn't DRY.
You should really define your own query in the entity repository, it's simple and best practice.
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
public function findAll()
{
return $this->findBy(array(), array('username' => 'ASC'));
}
}
Then you must tell your entity to look for queries in the repository:
/**
* @ORM\Table(name="User")
* @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\Repository\UserRepository")
*/
class User
{
...
}
Finally, in your controller:
$this->getDoctrine()->getRepository('AcmeBundle:User')->findAll();
Solution 2 - Symfony
$this->getDoctrine()->getRepository('MyBundle:MyTable')->findBy([], ['username' => 'ASC']);
Solution 3 - Symfony
Simple:
$this->getDoctrine()->getRepository('AcmeBundle:User')->findBy(
array(),
array('username' => 'ASC')
);
Solution 4 - Symfony
It's useful to look at source code sometimes.
For example findAll
implementation is very simple (vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php
):
public function findAll()
{
return $this->findBy(array());
}
So we look at findBy
and find what we need (orderBy
)
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
Solution 5 - Symfony
This works for me:
$entities = $em->getRepository('MyBundle:MyTable')->findBy(array(),array('name' => 'ASC'));
Keeping the first array empty fetches back all data, it worked in my case.
Solution 6 - Symfony
You need to use a criteria, for example:
<?php
namespace Bundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Collections\Criteria;
/**
* Thing controller
*/
class ThingController extends Controller
{
public function thingsAction(Request $request, $id)
{
$ids=explode(',',$id);
$criteria = new Criteria(null, <<DQL ordering expression>>, null, null );
$rep = $this->getDoctrine()->getManager()->getRepository('Bundle:Thing');
$things = $rep->matching($criteria);
return $this->render('Bundle:Thing:things.html.twig', [
'entities' => $things,
]);
}
}
Solution 7 - Symfony
Look at the Doctrine API source-code :
class EntityRepository{
...
public function findAll(){
return $this->findBy(array());
}
...
}
Solution 8 - Symfony
findBy method in Symfony excepts two parameters. First is array of fields you want to search on and second array is the the sort field and its order
public function findSorted()
{
return $this->findBy(['name'=>'Jhon'], ['date'=>'DESC']);
}
Solution 9 - Symfony
You can sort an existing ArrayCollection using an array iterator.
assuming $collection is your ArrayCollection returned by findAll()
$iterator = $collection->getIterator();
$iterator->uasort(function ($a, $b) {
return ($a->getPropery() < $b->getProperty()) ? -1 : 1;
});
$collection = new ArrayCollection(iterator_to_array($iterator));
This can easily be turned into a function you can put into your repository in order to create findAllOrderBy() method.
Solution 10 - Symfony
Try this:
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MyBundle:MyTable')->findBy(array(), array('username' => 'ASC'));
Solution 11 - Symfony
I use an alternative to the solution that wrote nifr.
$resultRows = $repository->fetchAll();
uasort($resultRows, function($a, $b){
if ($a->getProperty() == $b->getProperty()) {
return 0;
}
return ($a->getProperty()< $b->getProperty()) ? -1 : 1;
});
It's quicker than the ORDER BY clause, and without the overhead of the Iterator.
Solution 12 - Symfony
Modify the default findAll function in EntityRepository like this:
public function findAll( array $orderBy = null )
{
return $this->findBy([], $orderBy);
}
That way you can use the ''findAll'' on any query for any data table with an option to sort the query