PHP: Naturally sorting multidimension arrays by string values

This is just one of those things that I have to do often enough for it to be useful to have it close at hand, but not often enough that I actually remember how to do it.

I often run into this problem when using CakePHP, as results are returned from the database in a multidimensional array. Since MySQL doesn’t (as far as I’m aware) have an easy natural sort option, even if the results are sorted by name, strings that have numbers in can end up in the wrong order, e.g. “Item 10” before “Item 2”. Using a combination of usort() and strnatcasecmp(), it’s pretty easy to naturally sort an array by a value that appears in each subarray, like this:

usort($array, function($a, $b) {
    return strnatcasecmp($a['name'], $b['name']);
});

As an example, say I got the following array back from MySQL:

$array = array(
    array(
        'id' => 265,
        'name' => 'Drawer 1'
    ),
    array(
        'id' => 971,
        'name' => 'Drawer 10'
    ),
    array(
        'id' => 806,
        'name' => 'Drawer 2'
    ),
    array(
        'id' => 429,
        'name' => 'Drawer 20'
    )
);

“Drawer 10” comes before “Drawer 2”, which is obviously not what I want. Using strcasecmp() as the sort function on the above array wouldn’t change it, but using strnatcasecmp() gives the required result:

$array = array(
    array(
        'id' => 265,
        'name' => 'Drawer 1'
    ),
    array(
        'id' => 806,
        'name' => 'Drawer 2'
    ),
    array(
        'id' => 971,
        'name' => 'Drawer 10'
    ),
    array(
        'id' => 429,
        'name' => 'Drawer 20'
    )
);

3 Replies to “PHP: Naturally sorting multidimension arrays by string values”

  1. Superb!!!!!!! I spent 3 hours on google to find the solution but every solution gives wrong result. But at last, when i tried your way , i was feeling lucky.

    Thank you again

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.