tags:

views:

233

answers:

3

Let's say I've got two tables: cities and countries. The City model belongsTo a Country. Now, when I display lists of cities, I want them to be ordered by country name and then city name.

I tried this in my City model class:

var $order = array('Country.name' => 'asc', 'City.name' => 'asc');

The sort order works correctly for my index page, but I get errors in several places where the model has been asked not to load associated models. Do I have to change the order parameters when I change which tables are loaded, or is there a smarter way to do this?

For now, I think I'll make the default order definition be City.name and then just change it to Country.name and City.name on the index page. That way it's safe by default, and I shouldn't get unexpected errors.

Update: As Rob suggested you can specify order parameters in the model associations. The query builder applies them like this:

  1. If there is an order field on the main model, apply it first.
  2. Walk through all the associated models in the order they appear. If the association includes an order parameter, add it to the end of the list.

To implement my example, I would do it like this:

class City extends AppModel {
    var $belongsTo = array(
        'Country' => array(
            'order' => array('Country.name' => 'asc', 'City.name' => 'asc')));
}

One caution: if you turn off City.recursive, then the cities will be unsorted. However, I'm usually retrieving only one record when I've turned off recursion.

A: 

this is untested, but the idea is in the country model you can do

hasMany = array('City');
function beforeFind()
{
    foreach($this->hasMany as $model)
    {
        $this->order[] = $model['className'].'.'.'ASC';
    }
}

not worth doing IMO. ur way is fine.

Funky Dude
+2  A: 

Have you tried defining the order directly in your association? I've never needed to do this, so I can't swear it will do what you're after, but:

class City extends AppModel {
    $belongsTo = array(
        'Country' => array(
            'Order' => 'Country.name'
        )
    );
}

You could do something similar for your Country model, of course.

Rob Wilkerson
This works. See my update in the question for the details of how the order fields interact with each other.
Don Kirkby
A: 
class City extends AppModel {
    var $order = array('name'=>'asc');
    var $belongsTo = array(
        'Country' => array(
            'order' => array('Country.name' => 'asc')));
}

this way your cities will always be ordered correct no matter what recursive level

Ceeram
In my testing, the $order field on the City model is applied before any order options in the associated models. In this case, I think it would order by City.name, Country.name. Not what I want, unfortunately.
Don Kirkby