Custom Sorts

AZIndex is great for creating alphabetical indwinexes, it’s what the plugin does for a living.  But, with a little extra code, you can use it to create other types of indexes too.  Perhaps you’re using WordPress to maintain a catalogue of parts that you would like to sort by part number.  If those numbers are not all the same length, then they will not be sorted in the right order by the default AZIndex sort.

There are also some cases where AZIndex may not always deliver the expected result—especially when using other languages.  While it would be great if the plugin always delivered the correct result, it does not always happen.

So, what can you do if you can’t get the sorting you need from AZIndex but like everything else about the plugin?  Well, there are two different things you can do customize the sorting in your index:

  1. Use an item filter to modify the data you are going to sort
  2. Use a custom comparison function in the sort

Item Filter

An item filter is called before the index is sorted and can be used to modify the data in preparation for the sort.  For example, if you want to have an index where your posts are sorted in the order of the number of comments they have received, you can do this by using the filter code to query the number of comments each post has and placing that number in the sort-head field in the array you are passed (you would have to add leading zeros to make all the numbers line up and sort correctly, unless you also use a custom comparison function, of course).  You could also add the comment count to one of the displayed fields (say, at the beginning of the  head field) and end up with a cool index of all your posts in order of popularity!

There is much more information how to create and use an item filter on the Item Filter Reference Page.

Custom Comparison Function

A custom comparision function is called during the sort itself, as many times as is necessary to get the index sorted into the correct order.  For very large indexes, this can be many, many times.  If you add your own comparison function, you are in full control over how the index will be sorted.  These are the steps to follow:

  1. On the index settings page, select the following advanced option:

    • Use a customized comparison function for sorting the index
  2. A new text box titled Custom comparison function will appear at the bottom of the settings page.  Type in the name of your comparison function (e.g. my_compare) into the text box and save the settings.
  3. Now all you need to do is create your comparison function.  Find a place to add the function—creating another plugin for it would be great, or you could put it in the functions.php file in your current theme directory.  It doesn’t matter as long as it is in a place where WordPress can find it.

The comparison function needs to have the following signature:

function my_compare($item1, $item2) {
    /* My comparison code goes here */
}

$item1 and $item2 are the objects to be compared with each other.  They are associative arrays (arrays with key/value pairs) containing data about two of the items in the index.  They have the following keys:

id Post id – the id of the post linked to by this item.
initial The initial character in the heading of the item. Useful when the index is divided up into alphabetical sections.
head The item’s heading string, as it will be displayed in the index
subhead The item’s subheading string, as it will be displayed in the index
desc The item’s description string, as it will be displayed in the index
sort-head The item’s sorted heading string – used only when sorting the index
sort-subhead The item’s sorted subheading string – used only when sorting the index
sort-desc The item’s sorted description string – used only when sorting the index
key Category/tag id of the item – only if category/tag is selected as the heading for the index.

AZIndex normally uses sort-head, sort-subhead, and sort-desc, for sorting, in that order.  The sort values in the item may be different from the display values, depending on the settings used for the index, so it is usually advisable to use the sort values in you comparison function too, but the choice is yours.

The value you return from the function determines the order of the two items.  The plugin uses the PHP function usort (sort an array by values using a user-defined comparison function) and defines the return value in this way:

The comparison function must return an integer less than, equal
to, or greater than zero if the first argument is considered to
be respectively less than, equal to, or greater than the second.

In other words, if $item1 should appear above $item2 in the index, return an integer less than zero. Otherwise the return value should be greater than zero.  If you return zero the result is undefined, so your function should only return zero if you really do not care which item appears before the other.

Here is a simple example of a custom comparison function. If the headings in the index are all numbers, then you can sort the index in ascending numerical order with this one-line function:

function my_integer_compare($item1, $item2) {
    return ($item1['sort-head'] - $item2['sort-head']);
}

Notes About Custom Sorts

  • For most types of custom sort, it is probably quicker and more convenient to use an item filter to modify your items so that the default AZIndex sort will give you the result you need.  That way, you only modify each item once before each sort rather than, perhaps, many times during each sort.  Sometimes, however, a custom compare function may be the easier solution, or you might even need to use both to get the desired result.  The choice is yours, depending on the circumstances.
  • Be careful about querying information about each post in a custom comparison function.  If you have a very large index, the query could be executed thousands of times and may hammer your database.  I am not sure how good WordPress’s internal caching is, so you could be okay, but it is always advisable not to do too many complex and time consuming things during a custom compare function.  Keep it quick!
  • PHP support for collation (the sorting of words according to local language rules) does not work with UTF-8 on Windows.  Therefore, before the sort begins (and after the item filter is called) the strings in sort-head, sort-subhead, and sort-dec, are all converted into the local windows codepage running on the server.  This means that if you access these values in your custom comparison function, they will not be multibyte UTF-8 strings if your blog is running on Windows.  These values will always be valid UTF-8 strings when your server is running on Linux.
  • You can call the default AZIndex comparison function from your function.  The name of the function is az_compare and takes the same two parameters as the your custom comparison function.  For example, to sort the index in reverse alphabetical order, you can do this:
    function my_reverse_compare($item1, $item2) {
        return az_compare($item2['sort-head'], $item1['sort-head']);
    }
  • The index option “Display alphabetical headings” may not work well with your custom sort.  There isn’t much you can do at the moment to solve that problem except to turn headings off.
Continue to the next page »