Sort Numerically

If you read Tip #1 "Add a New Entry Field" you probably were wondering why I named the new field "DisplayOrder" and guessed that there was more to it than just a randomly picked field name. Well, wonder no more. In this tip I will tell you how to modify Movable Type so you can use the DisplayOrder field for sorting your entries based upon a numerical value.


Movable Type generally uses text to sort records. For instance, if you use the Title field for sorting your entries with a statement such as:

<$MTEntries sort_by="Title" sort_order="descend"$>

then the entries will be sorted using the Title field and will be ordered alpabetically from "Z" to "A" which is fine if that is what you want. However, if you want to sort on a sequence of numbers, the result is not always what you may want. This is due to the way that Perl sorts strings. For instance, suppose you have a sort_by field that contains the values 1, 2, 10, 3 and sort_order="ascend". The result will be 1, 10, 2, 3... not exactly what you would expect; probably your natural incilination would be to expect that the result would be 1, 2, 3, 10... mine is. Now, you could force the issue by entering the string with leading zeros, i.e., 001, 002, 010, 003 which would give you the desired result of 001, 002, 003, 010. If you are as lazy as I am, it is just too much to expect that you will enter the values properly. I almost never do. So what to do? Perl is a rather interesting language and has a solution for this problem. Just use the numerical sort operator and it works just the way you would expect.


OK, the problem is not Perl so how do we implement this in Movable Type? The solution is pretty simple. First we need to locate the code that does the sorting (this took me quite a while) and then modify it with a special case so that if the field used is our DisplayOrder field, the sorting will be numerical. Here we go!


Step 1: Add a DisplayOrder field

Obviously, the first thing we need to do is add a field to the Entry records that we can use for numerically sorting Entry records. I described this in Tip #1.


Step 2: Create the Numerical Sort

I will assume that you have already made a backup of all your files when you created the new field. If not, do it now!


Open the Context.pm file and search for @entries = $so eq 'ascend'. It will be at about line 410 and you will see:

@entries = $so eq 'ascend' ?
  sort { $a->$col() cmp $b->$col() } @entries :
  sort { $b->$col() cmp $a->$col() } @entries;


This is the code that sorts the Entry records. Replace the original code with:

if ($col eq 'displayorder') {
  @entries = $so eq 'ascend' ?
    sort { $a->$col() <=> $b->$col() } @entries :
    sort { $b->$col() <=> $a->$col() } @entries;
} else {
  @entries = $so eq 'ascend' ?
    sort { $a->$col() cmp $b->$col() } @entries :
    sort { $b->$col() cmp $a->$col() } @entries;
  }


Save the context.pm file and close it.


All you need to do now is to modify your template(s) to use the new field for sorting. This can easily be done by modifying your <$MTEntries$> tag to something like:

<$MTEntries sort_by="DisplayOrder" sort_order="ascend"$>


Good Blogging!

   

© 2002 bnsDesigns