My name is  
Jurgens du Toit.
Systems Developer.
Problem Solver.

About Me

Technology and Solving Problems are my passion. I'm a South African that loves my wife, life, and coding.

I'm writing a book!

The Logstash Config Guide

Buy it now on Leanpub

17 September 2013

Setting a default order for Doctrine 2 / Symfony 2

By Jurgens du Toit

Usually when you’re working with data you expect some kind of default ordering. It might be the primary key, or, more commonly, the data set will be ordered by a timestamp field or the data’s most important property. In Doctrine you can create custom repository classes to tweak queries to your liking:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// src/Acme/StoreBundle/Entity/ProductRepository.php
namespace Acme\StoreBundle\Entity;

use Doctrine\ORM\EntityRepository;

class ProductRepository extends EntityRepository
{
    public function findAllOrderedByName()
    {
        return $this->getEntityManager()
            ->createQuery(
                'SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC'
            )
            ->getResult();
    }
}
?>

This is all fine and dandy, but do you really want to repeat yourself everytime you write a query for a model that will almost always be ordered by the same field? Or get caught out by calls to default repository methods that don’t use the ordering you like? No, you don’t. Enter this piece of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
// src/Acme/StoreBundle/Entity/ProductRepository.php
namespace Acme\StoreBundle\Entity;

use Doctrine\ORM\EntityRepository;

class ProductRepository extends EntityRepository
{
    public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
    {
        // Default Ordering
        $orderBy = $orderBy === null ? array('added' => 'desc') : $orderBy;

        // Default Filtering
        if (array_key_exists('active', $criteria) === false) {
            $criteria['active'] = 1;
        }
        return parent::findBy($criteria, $orderBy, $limit, $offset);
    }
}
?>

The findBy method of the EntityRepository class is the method used by most (if not all) of the the repository methods that fetch data. This includes findBy methods where you can specify an arbitrary column and value:

1
2
3
4
<?php
// find a group of products based on an arbitrary column value
$products = $repository->findByPrice(19.99);
?>

So to ensure a default ordering, we override this method and check if an orderBy clause has been set. If not, set it to our default ordering — in this case by the added field, descending. For good measure we also add default filtering — the active field needs to equal 1. Once that’s done, call the parent method with the default values set.

Easy as π

blog comments powered by Disqus