usort

(PHP 4, PHP 5)

usortСортирует массив по значениям используя пользовательскую функцию для сравнения элементов

Описание

bool usort ( array &$array , callable $cmp_function )

Эта функция сортирует элементы массива, используя для сравнения значений callback-функцию, предоставленную пользователем. Используйте эту функцию, если вам нужно отсортировать массив по какому-нибудь необычному признаку.

Замечание:

Если два элемента исходного массива равны, их порядок относительно друг друга в отсортированном массиве неопределён.

Замечание: Эта функция присваивает новые ключи элементам массива. Она удалит все существующие ключи, а не просто переупорядочит их.

Список параметров

array

Входной массив.

cmp_function

Функция сравнения должна возвращать целое, которое меньше, равно или больше нуля, если первый аргумент является соответственно меньшим, равным или большим чем второй.

int callback ( mixed $a, mixed $b )
Предостережение

Возвращаемые нецелочисленные (non-integer) значения из функции сравнения, такие как float, будут приводиться к типу integer. Поэтому такие значения, как 0.99 и 0.1, будут приводиться к целому числу 0, что указывает на равенство сравниваемых значений.

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Список изменений

Версия Описание
4.1.0 Представлен новый алгоритм сортировки. Функция cmp_function не сохраняет исходный порядок одинаковых элементов.

Примеры

Пример #1 Пример использования usort()

<?php
function cmp($a$b)
{
    if (
$a == $b) {
        return 
0;
    }
    return (
$a $b) ? -1;
}

$a = array(32561);

usort($a"cmp");

foreach (
$a as $key => $value) {
    echo 
"$key$value\n";
}
?>

Результат выполнения данного примера:

0: 1
1: 2
2: 3
3: 5
4: 6

Замечание:

Очевидно, что для этого тривиального случая более подходит функция sort().

Пример #2 Пример использования функции usort() с многомерными массивами

<?php
function cmp($a$b)
{
    return 
strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits"cmp");

while (list(
$key$value) = each($fruits)) {
    echo 
"\$fruits[$key]: " $value["fruit"] . "\n";
}
?>

При сортировке многомерного массива переменные $a и $b содержат ссылки на первые два индекса массива.

Результат выполнения данного примера:

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

Пример #3 Пример использования usort() с методом класса

<?php
class TestObj {
    var 
$name;

    function 
TestObj($name)
    {
        
$this->name $name;
    }

    
/* Это статическая функция сравнения: */
    
static function cmp_obj($a$b)
    {
        
$al strtolower($a->name);
        
$bl strtolower($b->name);
        if (
$al == $bl) {
            return 
0;
        }
        return (
$al $bl) ? +: -1;
    }
}

$a[] = new TestObj("c");
$a[] = new TestObj("b");
$a[] = new TestObj("d");

usort($a, array("TestObj""cmp_obj"));

foreach (
$a as $item) {
    echo 
$item->name "\n";
}
?>

Результат выполнения данного примера:

b
c
d

Пример #4 Пример использования функции usort() с применением анонимной функции для сортировки многомерного массива

<?php
$array
[0] = array('key_a' => 'z''key_b' => 'c');
$array[1] = array('key_a' => 'x''key_b' => 'b');
$array[2] = array('key_a' => 'y''key_b' => 'a');

function 
build_sorter($key) {
    return function (
$a$b) use ($key) {
        return 
strnatcmp($a[$key], $b[$key]);
    };
}

usort($arraybuild_sorter('key_b'));

foreach (
$array as $item) {
    echo 
$item['key_a'] . ', ' $item['key_b'] . "\n";
}
?>

Результат выполнения данного примера:

y, a
x, b
z, c

Смотрите также

Коментарии

Needed a date sort and I didn't know if one was available so I wrote one. Maybe it'll help someone:

<?php
function DateSort($a,$b,$d="-") {
    if (
$a == $b) {
        return 
0;
    } else { 
//Convert into dates and compare
       
list($am,$ad,$ay)=split($d,$a);
        list(
$bm,$bd,$by)=split($d,$b);
        if (
mktime(0,0,0,$am,$ad,$ay) < mktime(0,0,0,$bm,$bd,$by)) {
            return -
1;
        } else {
            return 
1;
        }
    }
}
?>

$d is the delimeter
2000-09-19 02:35:38
http://php5.kiev.ua/manual/ru/function.usort.html
when using usort to refer to a function inside a class i have succesfully used:

<?php usort($myarray,array($this,"cmp")); ?>
2001-03-20 07:16:09
http://php5.kiev.ua/manual/ru/function.usort.html
These functions will sort an array by more than one element. The elements to sort by is specified in $sortArr. If you eg. want to sort by $destArr[]["sortBy2"][0] you add '["sortBy2"][0]' to $sortArr. Use it as much as you want!! If you modify it, please let me know...

<?php
//The functions
function compare($a$b) {
    return 
cmpRec(0$a$b);
}

function 
cmpRec($i$a$b) {
    global 
$sortArr;
    if(
$i == sizeof($sortArr)) {
        return 
0;
    }
   
$avalue '$avalue = $a'.$sortArr[$i].';';
   
$bvalue '$bvalue = $b'.$sortArr[$i].';';
    eval(
$avalue);
    eval(
$bvalue);
        if(
$avalue == $bvalue) {
        return 
cmpRec($i+1$a$b);
    } else {
        return (
$avalue $bvalue) ? (1) : (-1); 
    }
}

//For testing the functions
$destArr = array( array( "sortBy1" => 2"sortBy2" => array( "Fish""eat seafood" )), array( "sortBy1" => 1"sortBy2" => array( "Lions""eat everything" )), array( "sortBy1" => 1"sortBy2" => array( "Bird""eat birdfood" )) ); 
$sortArr = array( '["sortBy1"]''["sortBy2"][0]' );
print_r($destArr);
usort($destArr"compare");
reset($destArr);
print_r($destArr);
?>
2001-06-29 08:23:20
http://php5.kiev.ua/manual/ru/function.usort.html
For sort multi-array by specific index

<?php
function cmp ($a$b)
{   
 global 
$w_o;
 if (
$a[$w_o] == $b[$w_o]) return 0;
 return (
$a[$w_o] < $b[$w_o]) ? -1;
}
# the index is the second element of 
# each row

$w_o =1;
usort($my_arry_info,"cmp");
?>
2001-07-17 18:08:46
http://php5.kiev.ua/manual/ru/function.usort.html
This lets you sort an associative multi-dimensional array by multiple key/field names.  Much similiar to the SQL clause ORDER BY.  Enjoy.

<?php
function cmp ($a$b) {

   
// Populate this array with your values...
    // Below is the SQL equivalent of
    // select * from blah ORDER BY date desc, type asc, name asc

   
$vals = array(
       
'date' => 'd',
       
'type' => 'a',
       
'name' => 'a'
   
);

    while(list(
$key$val) = each($vals)) {

        if(
$val == "d") {
            if (
$a["$key"] > $b["$key"]) {
                return -
1;
            }
            if (
$a["$key"] < $b["$key"]) {
                return 
1;
            }
        }

        if(
$val == "a") {
            if (
$a["$key"] < $b["$key"]) {
                return -
1;
            }
            if(
$a["$key"] > $b["$key"]) {
                return 
1;
            }
        }

    }

}
?>
2001-08-24 21:58:32
http://php5.kiev.ua/manual/ru/function.usort.html
just for debugging purposes, usort does not complain if its argument function is not defined, i.e.:

<?php usort($my_array,"non existant function"); ?>

will not do anything...
2001-09-25 14:48:04
http://php5.kiev.ua/manual/ru/function.usort.html
Example 3 above does not work with 4.0.4pl1, unless you write the uasort line as follows:
uasort($a, array ($a[0], "cmp_obj"));

(I assume any instance of the object: a[0] or a[1] or a[2] would work as well)

It does not work at all with associative arrays of objects.
2002-01-15 22:28:01
http://php5.kiev.ua/manual/ru/function.usort.html
This function will sort on more then one values, test and have fun

<pre>
<?php

  $array
[0]['name'] = "a";
 
$array[0]['id'] = 3;

 
$array[1]['name'] = "a";
 
$array[1]['id'] = 2;

 
$array[2]['name'] = "a";
 
$array[2]['id'] = 5;

 
$array[3]['name'] = "b";
 
$array[3]['id'] = 8;

 
$array[4]['name'] = "b";
 
$array[4]['id'] = 1;

 
$array[5]['name'] = "b";
 
$array[5]['id'] = 0;

 
$array[6]['name'] = "c";
 
$array[6]['id'] = 5;

 
$array[7]['name'] = "c";
 
$array[7]['id'] = 7;

 
$array[8]['name'] = "c";
 
$array[8]['id'] = 3;

 
print_r($array);

 
$sort_array[0]['name'] = "name";
 
$sort_array[0]['sort'] = "ASC";
 
$sort_array[0]['case'] = TRUE;

 
$sort_array[1]['name'] = "id";
 
$sort_array[1]['case'] = FALSE;

 
sortx($array$sort_array);

 
print_r($array);

  function 
sortx(&$array$sort = array()) {
   
$function '';
    while (list(
$key) = each($sort)) {
      if (isset(
$sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       
$function .= 'if (strtolower($a["' $sort[$key]['name'] . '"])<>strtolower($b["' $sort[$key]['name'] . '"])) { return (strtolower($a["' $sort[$key]['name'] . '"]) ';
      } else {
       
$function .= 'if ($a["' $sort[$key]['name'] . '"]<>$b["' $sort[$key]['name'] . '"]) { return ($a["' $sort[$key]['name'] . '"] ';
      }
      if (isset(
$sort[$key]['sort'])&&($sort[$key]['sort'] == "DESC")) {
       
$function .= '<';
      } else {
       
$function .= '>';
      }
      if (isset(
$sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       
$function .= ' strtolower($b["' $sort[$key]['name'] . '"])) ? 1 : -1; } else';
      } else {
       
$function .= ' $b["' $sort[$key]['name'] . '"]) ? 1 : -1; } else';
      }
    }
   
$function .= ' { return 0; }';
   
usort($arraycreate_function('$a, $b'$function));
  }

?>
</pre>
2002-07-02 07:10:26
http://php5.kiev.ua/manual/ru/function.usort.html
Here is a simple example of converting a timestamp date("U") into a date. This sorts by that day and then by string value alphabetically.

I hope it saves someone some time... Happy PHP'in!

<?php
//data to sort
$shared[0]["page_id"] = "2025731470";
$shared[1]["page_id"] = "2025731450";
$shared[2]["page_id"] = "1025731456";
$shared[3]["page_id"] = "1025731460";
$shared[0]["username"] = "larry";
$shared[1]["username"] = "alvin";
$shared[2]["username"] = "garth";
$shared[3]["username"] = "harvy";

//function to convert timestamp to date
function convert_timestamp($timestamp){
   
$limit=date("U");
   
$limiting=$timestamp-$limit;
    return 
date ("Ymd"mktime (0,0,$limiting));
}
//comparison function
function cmp ($a$b) {
   
$l=convert_timestamp($a["page_id"]);
   
$k=convert_timestamp($b["page_id"]);
    if(
$k==$l){
        return 
strcmp($a["username"], $b["username"]);
    }else{
        return 
strcmp($k$l);
    }
}

//sort array
usort($shared"cmp");

//display sorted info
while (list ($key$value) = each ($shared)) {
    echo 
"\$shared[$key]: ";
    echo 
$value["page_id"];
    echo 
" username: ";
    echo 
$value["username"];
    echo 
"<break_tag>";
}
?>

This will output:
$shared[0]: 2025731450   username: alvin
$shared[1]: 2025731470   username: larry
$shared[2]: 1025731456   username: garth
$shared[3]: 1025731460   username: harvy
2002-07-15 08:55:43
http://php5.kiev.ua/manual/ru/function.usort.html
If you want to sort an array according to another array acting as a priority list, you can use this function.

<?php
function listcmp($a$b)
{
  global 
$order;

  foreach(
$order as $key => $value)
    {
      if(
$a==$value)
        {
          return 
0;
          break;
        }

      if(
$b==$value)
        {
          return 
1;
          break;
        }
    }
}

$order[0] = "first";
$order[1] = "second";
$order[2] = "third";

$array[0] = "second";
$array[1] = "first";
$array[2] = "third";
$array[3] = "fourth";
$array[4] = "second";
$array[5] = "first";
$array[6] = "second";

usort($array"listcmp");

print_r($array);
?>
2002-09-20 12:29:51
http://php5.kiev.ua/manual/ru/function.usort.html
If you've used ADO before, you may have used the Sort property on a recordset.  It's very powerful - you can add a nice ORDER BY clause after getting the recordset from the database.  It's especially helpful if you want to show a list on a web page and make the column headings links that cause the list to resort on that column.

I wanted to do the same thing with mysql recordsets, but it looks like you have to have the ORDER BY in your query.  I re-worked the example from johan_land at yahoo dot com above for sorting multidimensional arrays.  When I get a mysql recordset, I create an array with all of the records like this:

<?php
$aaRows
[]    = array();
if (
mysql_num_rows($rsRows) > 0)
    while (
$aRow mysql_fetch_array($rsRowsMYSQL_ASSOC))
       
$aaRows[]    = $aRow;
?>

At this point $aaRows is an array of arrays - it's a numeric-indexed array containing records from the recordset, which themselves are associative arrays.  The following code takes the array of records as the first parameter, and an array of fields to sort - each field is an associative array, where 'name' is the db field name, and 'dir' is the direction to sort.  If dir is 'DESC' (case-insensitive), it will sort descending.  Any other value (including not setting one) will cause it to sort ascending.

<?php
function sortRows(&$a_aaRows$a_aaSortCriteria)
{
    GLOBAL   
$g_aaSortArray;

    function 
compare($a_aRow1$a_aRow2$a_lField 0)
    {
        GLOBAL   
$g_aaSortArray;

       
$lCompareVal    0;

        if (
$a_lField count($g_aaSortArray))
        {
           
$sSortFieldName    $g_aaSortArray[$a_lField]['name'];
           
$sSortFieldDir    $g_aaSortArray[$a_lField]['dir'];

           
$vValue1    = eval('return $a_aRow1[' $sSortFieldName '];');
           
$vValue2    = eval('return $a_aRow2[' $sSortFieldName '];');

            if (
$vValue1 == $vValue2)
               
$lCompareVal    compare($a_aRow1$a_aRow2$a_lField 1);
            else
            {
               
$lCompareVal    =    $vValue1 $vValue2 : -1;
                if (
strtolower(substr($sSortFieldDir04)) == 'desc')
                   
$lCompareVal    = -$lCompareVal;
            }
        }

        return 
$lCompareVal;
    }

   
$g_aaSortArray    $a_aaSortCriteria;
   
usort($a_aaRows'compare');
}
?>

When I call it it looks something like this:

<?php
sortRows
($aaRows, array(array('name' => 'STATE''dir' => 'ASC'), array('name' => 'CITY''dir' => 'DESC')));
?>
2002-10-24 19:37:56
http://php5.kiev.ua/manual/ru/function.usort.html
The sort functions do nothing if identical keys exist.  Of course, you shouldn't have identical keys anyway, but this just might save someone else the oodles of time it took me to figure out while using multi-dimentional arrays:

<?php
class myArticleList {
// ... //
 
function &getList () {

   
// works
       
$a = array ( 
                   
"articleList1" => array ( "2""3" ),
                   
"articleList2" => array ( "3" "4")
                 );
   
usort$a, array( $this"compareByTitle") );
     
   
// doesn't work
       
$b = array ( 
                   
"articleList" => array ( "2""3" ),
                   
"articleList" => array ( "3" "4")
                 );
   
usort$b, array( $this"compareByTitle") );
  }

  function 
compareByTitle$a$b ) {
 
// ... //
 
}
}
?>
2002-12-31 16:11:43
http://php5.kiev.ua/manual/ru/function.usort.html
here's another recursive multisort, however a clean and fast one that is class-based (but works as well outside classes) and does not uglify your global namespace at all. note that strnatcmp is used, but one could use something else of course.

btw, for arrays in which the rows/columns are 'swapped', use array_multisort().

<?php
class Banana {
    var 
$aData;//the array we want to sort.
   
var $aSortkeys;//the order in which we want the array to be sorted.
   
function _sortcmp($a$b$i=0) {
       
$r strnatcmp($a[$this->aSortkeys[$i]],$b[$this->aSortkeys[$i]]);
        if(
$r==0) {
           
$i++;
            if (
$this->aSortkeys[$i]) $r $this->_sortcmp($a$b$i+1);
        }
        return 
$r;
    }
    function 
sort() {
        if(
count($this->aSortkeys)) {
           
usort($this->aData,array($this,"_sortcmp"));
        }
    }
}
$B = new Banana;
$B->aData = array(
    array(
"name" => "hank""headsize" => "big""age" => 32),
    array(
"name" => "frank""headsize" => "huge""age" => 36)
);
$B->aSortkeys = array("age","name");
$B->sort();

?>
sorry for the ugly indenting, but i couldn't get it any better in this note adder thing.
2003-03-27 15:59:07
http://php5.kiev.ua/manual/ru/function.usort.html
Needed a quick, fairly uncluttered way of sorting an array of objects by a certain object attribute, so here's what I came up with. Uses one global array and usort(). Also accepts an optional sort direction argument (CSORT_ASC = sort ascending, CSORT_DESC = sort descending). Use it like this:

(assuming $myarray is your array, "index" is the attribute you want to sort by, and you want to sort in descending order)

      csort($myarray, "index", CSORT_DESC);

Hope this is of use to someone. Probably a better way to pull this off, but this works alright.

<?php
define
("CSORT_ASC",     1);
define("CSORT_DESC",     -1);

function 
csort_cmp(&$a, &$b)
{
    global 
$csort_cmp;

    if (
$a->$csort_cmp['key'] > $b->$csort_cmp['key'])
        return 
$csort_cmp['direction'];

    if (
$a->$csort_cmp['key'] < $b->$csort_cmp['key'])
        return -
$csort_cmp['direction'];

    return 
0;
}

function 
csort(&$a$k$sort_direction=CSORT_ASC)
{
    global 
$csort_cmp;

   
$csort_cmp = array(
       
'key'           => $k,
       
'direction'     => $sort_direction
   
);

   
usort($a"csort_cmp");

    unset(
$csort_cmp);
}
?>
2003-12-20 05:05:40
http://php5.kiev.ua/manual/ru/function.usort.html
As the manual says, "If two members compare as equal, their order in the sorted array is undefined." This means that the sort used is not "stable" and may change the order of elements that compare equal.

Sometimes you really do need a stable sort. For example, if you sort a list by one field, then sort it again by another field, but don't want to lose the ordering from the previous field. In that case it is better to use usort with a comparison function that takes both fields into account, but if you can't do that then use the function below. It is a merge sort, which is guaranteed O(n*log(n)) complexity, which means it stays reasonably fast even when you use larger lists (unlike bubblesort and insertion sort, which are O(n^2)). 

<?php
function mergesort(&$array$cmp_function 'strcmp') {
   
// Arrays of size < 2 require no action.
   
if (count($array) < 2) return;
   
// Split the array in half
   
$halfway count($array) / 2;
   
$array1 array_slice($array0$halfway);
   
$array2 array_slice($array$halfway);
   
// Recurse to sort the two halves
   
mergesort($array1$cmp_function);
   
mergesort($array2$cmp_function);
   
// If all of $array1 is <= all of $array2, just append them.
   
if (call_user_func($cmp_functionend($array1), $array2[0]) < 1) {
       
$array array_merge($array1$array2);
        return;
    }
   
// Merge the two sorted arrays into a single sorted array
   
$array = array();
   
$ptr1 $ptr2 0;
    while (
$ptr1 count($array1) && $ptr2 count($array2)) {
        if (
call_user_func($cmp_function$array1[$ptr1], $array2[$ptr2]) < 1) {
           
$array[] = $array1[$ptr1++];
        }
        else {
           
$array[] = $array2[$ptr2++];
        }
    }
   
// Merge the remainder
   
while ($ptr1 count($array1)) $array[] = $array1[$ptr1++];
    while (
$ptr2 count($array2)) $array[] = $array2[$ptr2++];
    return;
}
?>
2004-01-07 22:22:26
http://php5.kiev.ua/manual/ru/function.usort.html
<?php
/*
This is a class I built to sort parent/child relationships of array elements.
I post this here, because thanks to usort, you can also assign an explicit order
to the elements.

I first built this to sort categories and subcategories.

My database has four fields. category_id, parent_id, category_name, category_position

$rows is an associative array from the database with my categories.
*/
$rows = array( 0=>array('category_id'=>1,'parent_id' =>3,'category_name' =>'Second Child','category_position'=>2),
                   
1=>array('category_id' =>2,'parent_id' =>0,'category_name' =>'Second Parent','category_position'=>2),
                   
2=>array('category_id' =>3,'parent_id' =>0,'category_name' =>'First Parent','category_position'=>1),
                   
3=>array('category_id' =>4,'parent_id' =>0,'category_name' =>'Third Parent','category_position'=>3),
                   
4=>array('category_id' =>5,'parent_id' =>3,'category_name' =>'First Child','category_position'=>1),
                   
5=>array('category_id' =>6,'parent_id' =>5,'category_name'=>'Second Sub-Child','category_position'=>2),
                   
6=>array('category_id' =>7,'parent_id' =>5,'category_name' =>'First Sub-Child','category_position'=>1)
                    );

$ordered chain('category_id''parent_id''category_position'$rows);

foreach(
$ordered as $item)
{
    echo 
str_repeat('------'$item['indent']).$item['category_name'].'<br>';
}

/*

Output

First Parent
------First Child
------------First Sub-Child
------------Second Sub-Child
------Second Child
Second Parent
Third Parent

You can have it only return a certain "branch" if you specify a root_id.
Aditionally, you can keep it by going to deep by specifying max-level.

Hope someone finds this useful, I sure would have liked to see this here a week ago.

Ah yes... and the code that runs it.
*/

function chain($primary_field$parent_field$sort_field$rows$root_id=0$maxlevel=25)
{
   
$c = new chain($primary_field$parent_field$sort_field$rows$root_id$maxlevel);
    return 
$c->chain_table;
}

class 
chain
{
    var 
$table;
    var 
$rows;
    var 
$chain_table;
    var 
$primary_field;
    var 
$parent_field;
    var 
$sort_field;
   
    function 
chain($primary_field$parent_field$sort_field$rows$root_id$maxlevel)
    {
       
$this->rows $rows;
       
$this->primary_field $primary_field;
       
$this->parent_field $parent_field;
       
$this->sort_field $sort_field;
       
$this->buildChain($root_id,$maxlevel);
    }

    function 
buildChain($rootcatid,$maxlevel)
    {
        foreach(
$this->rows as $row)
        {
           
$this->table[$row[$this->parent_field]][ $row[$this->primary_field]] = $row;
        }
       
$this->makeBranch($rootcatid,0,$maxlevel);
    }
           
    function 
makeBranch($parent_id,$level,$maxlevel)
    {
       
$rows=$this->table[$parent_id];
        foreach(
$rows as $key=>$value)
        {
           
$rows[$key]['key'] = $this->sort_field;
        }
       
       
usort($rows,'chainCMP');
        foreach(
$rows as $item)
        {
           
$item['indent'] = $level;
           
$this->chain_table[] = $item;
            if((isset(
$this->table[$item[$this->primary_field]])) && (($maxlevel>$level+1) || ($maxlevel==0)))
            {
               
$this->makeBranch($item[$this->primary_field], $level+1$maxlevel);
            }
        }
    }
}

function 
chainCMP($a,$b)
{
    if(
$a[$a['key']] == $b[$b['key']])
    {
        return 
0;
    }
    return(
$a[$a['key']]<$b[$b['key']])?-1:1;
}

?>
2004-01-27 00:05:15
http://php5.kiev.ua/manual/ru/function.usort.html
To sort multidimentional arrays .... by one key.

<?php
function multi_sort($tab,$key){
   
$compare create_function('$a,$b','if ($a["'.$key.'"] == $b["'.$key.'"]) {return 0;}else {return ($a["'.$key.'"] > $b["'.$key.'"]) ? -1 : 1;}');
   
usort($tab,$compare) ;
    return 
$tab ;
}
?>
2004-03-08 06:39:01
http://php5.kiev.ua/manual/ru/function.usort.html
The array_alternate_multisort function written by robert below doesn't work. There are several bugs in the code and it doesn't work when sorting by multiple keys because the order of the first key isn't taken into account when sorting by the second key and so on. Also, because robert uses strcasecmp the algorithm doesn't work properly with floats or other variable types. Here's the improved version:

<?php
   
function SortArray() {
       
$arguments func_get_args();
       
$array $arguments[0];
       
$code '';
        for (
$c 1$c count($arguments); $c += 2) {
            if (
in_array($arguments[$c 1], array("ASC""DESC"))) {
               
$code .= 'if ($a["'.$arguments[$c].'"] != $b["'.$arguments[$c].'"]) {';
                if (
$arguments[$c 1] == "ASC") {
                   
$code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? -1 : 1); }';
                }
                else {
                   
$code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? 1 : -1); }';
                }
            }
        }
       
$code .= 'return 0;';
       
$compare create_function('$a,$b'$code);
       
usort($array$compare);
        return 
$array;
    }
?>
2004-05-20 13:02:12
http://php5.kiev.ua/manual/ru/function.usort.html
Just something i stumbled about right now:
If the array consists of just one elemtent, the user-function is not called at all.

Although this surely makes sense, think of it if you want to use your order-function for adding extra data to your arrays...
2005-03-30 05:25:00
http://php5.kiev.ua/manual/ru/function.usort.html
The easiest way to compare two integers is just to take the second away from the first. For example, say you wanted to sort by an integer property of an object. Your comparison function would look like this:

<?php
function compare_counts($a$b) {
  return 
$a->count $b->count;
}
?>

This works because you don't necessarily have to return -1, 0 or 1, the manual states any integer less than, equal to or greater than 0 is OK.
2005-07-19 05:09:46
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
When I query a DB I usually put my record set inside of a multi-dimentional array.  I finally wrote a program that will allow you to sort your record set by column after you put it in an array.

<?php
$test 
= array();
$test[0]['name'] = 'jeremy';
$test[0]['email'] = 'lala@example.com';
$test[0]['phone'] = '123-123-1234';
$test[0]['trick'] = 'mezopia';

$test[1]['name'] = 'Amanda';
$test[1]['email'] = 'hot@example.com';
$test[1]['phone'] = '123-123-1235';
$test[1]['trick'] = 'youarecool';

$test[2]['name'] = 'john';
$test[2]['email'] = 'wowee@example.com';
$test[2]['phone'] = '123-123-3333';
$test[2]['trick'] = 'goneinanhour';

print_r(columnSort($test'name'));

function 
columnSort($unsorted$column) {
   
$sorted $unsorted;
    for (
$i=0$i sizeof($sorted)-1$i++) {
      for (
$j=0$j<sizeof($sorted)-1-$i$j++)
        if (
$sorted[$j][$column] > $sorted[$j+1][$column]) {
         
$tmp $sorted[$j];
         
$sorted[$j] = $sorted[$j+1];
         
$sorted[$j+1] = $tmp;
      }
    }
    return 
$sorted;
}
?>
2005-07-20 16:56:25
http://php5.kiev.ua/manual/ru/function.usort.html
In order to get a proper text sorting I have changed the arfsort() function submitted by jonathan(at)inetz(dot)com.

The one line I have changed is:

<?php
$strc 
strcmp$a[$f], $b[$f] );
?>

to

<?php
$strc 
strcmpstrtolower($a[$f]), strtolower($b[$f]) );
?>

It can now sort correctly for alphabetization.  Capital letters where getting in the way.

Sean
2005-09-23 17:46:12
http://php5.kiev.ua/manual/ru/function.usort.html
Instead of doing  :

<?php $strc strcmpstrtolower($a[$f]), strtolower($b[$f]) ); ?>

you could do this : 

<?php $strc strcasecmp$a[$f], $b[$f] ); ?>

which is more efficient and is does case insensitive comparison according to the current locale.
2006-01-16 03:44:54
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
For using usort inside a method in an object, where the callback sort method is in the same object, this works:

<?php usort($arr_to_sort, array($this"sort_terms_by_criteria")); ?>

If you wish to keep elements in their original or reverse order if they are the same length, just don't return zero for items that compare the same. Return a 1 or -1, as appropriate.
2006-04-06 01:28:52
http://php5.kiev.ua/manual/ru/function.usort.html
This will sort subnets correctly:

<?php

$zones 

array(
'192.168.11',
'192.169.12',
'192.168.13',
'192.167.14',
'192.168.15',
'122.168.16',
'192.168.17'
);

function 
sort_subnets ($a$b) {
   
$a_arr explode('.'$a);
   
$b_arr explode('.'$b);
    foreach (
range(0,3) as $i) {
        if ( 
$a_arr[$i] < $b_arr[$i] ) {
            return -
1;
        }
        elseif ( 
$a_arr[$i] > $b_arr[$i] ) {
            return 
1;
        }
    }
    return -
1;
}

usort($zones'sort_subnets');
print 
'<pre>';
print_r($zones);
print 
'</pre>';

?>
2006-10-16 04:58:36
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
If you want to sort an array of strings by the length of its values, you can write a better cmp-function than manually comparing string lengths with if-statements. Unfortunately, I see this bad technique in other people's code. I prefer using this:

<?php
function length_cmp$a$b ) {
    return 
strlen($a)-strlen($b) ;
}
?>

This function sorts the array in ascending order. If you want to sort descending, simply swap $a and $b either in the parameters or in the subtraction.

-Tim
2006-11-13 05:43:30
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
The sample function for having the sort function be a class method has a comment identifying the sorting function as static, however the function does not have the static keyword. In PHP 5 (at least as configured on my server), usort will fail, identifying the method as non-static. Preceding the function keyword with the static keyword fixed the problem.
2007-11-05 19:54:30
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
Here's how to use usort() within a class using a static function as a callback (using the example above):

<?php

class MyObj {
    var 
$name;

    function 
SampleObj($name){
       
$this->name $name;

       
usort($this->name, array(&$this"compareValues"));

    }

    static function 
compareValues($a$b){
       
$al strtolower($a->name);
       
$bl strtolower($b->name);
        if (
$al == $bl) {
            return 
0;
        }
        return (
$al $bl) ? +: -1;
    }
}

?>
2008-05-13 13:50:11
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
Here's how you can usort() a multidimensional array (like in example #2 above) within a class:

<?php usort($myArray, array("className""cmp")); ?>
2008-06-22 13:16:49
http://php5.kiev.ua/manual/ru/function.usort.html
<?php
/*---------------------------------------------------------
* my own home made easy object sort, which
* i cannot find anywhere on the net
* at all, tut. i can find only complicated ones,
* which brings me a headache.
*
* You can enhance it to return all sorts of error
* conditions if you wish,
* i need nothing but a false return upon failure to sort,
* so that is the only error i have here
*
* Example usage:
*
* INPUT                 -       $objects_array
// an array of objects for sorting

* PARAMETERS    -       property
// the property of the object to be sorted

* OUTPUT                -       $engine
// an engine object created by new,
// with your arrays of objects sorted according to your
// selected property
//( the sorting is done upon sort object creation )
*
* Code Examples
*
* $engine = new objSorter($objects_array);
// sorts on FIRST property -  default

* $engine = new objSorter($objects_array,'property');
// sort on ANY specific property
*--------------------------------------------------------*/

class objSorter 
{
var 
$property;
var 
$sorted;

    function 
ObjSorter($objects_array,$property=null
        {
           
$sample    $objects_array[0];
           
$vars    get_object_vars($sample);

        if (isset(
$property))
            {
            if (isset(
$sample->$property)) 
// make sure requested property is correct for the object
               
{   
               
$this->property $property;
               
usort($objects_array, array($this,'_compare'));
                }
            else
                {   
               
$this->sorted    false;
                return;   
                }
            }
        else
            {   
                list(
$property,$var)     = each($sample);
               
$this->property         $property;
               
usort($objects_array, array($this,'_compare'));
            }

       
$this->sorted    = ($objects_array);
        }

    function 
_compare($apple$orange
        {
       
$property    $this->property;
        if (
$apple->$property == $orange->$property) return 0;
        return (
$apple->$property $orange->$property) ? -1;
        }
// end class
?>

USAGE EXAMPLE
DUMP ORIGINAL
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => â‚¬ 899,970 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => â‚¬ 219,078 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => â‚¬ 3,272 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => â‚¬ 94,853 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => â‚¬ 677,180 )
user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => â‚¬ 144,540 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => â‚¬ 198,231 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => â‚¬ 763,860 )
user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => â‚¬ 302,352 )

SORTED by age

<?php
$objects               
= new ObjSorter($objects_array,'age');
if (
$objects->sorted)
{
$objects_array  $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
?>

user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => â‚¬ 302,352 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => â‚¬ 219,078 )
user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => â‚¬ 144,540 )
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => â‚¬ 899,970 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => â‚¬ 677,180 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => â‚¬ 763,860 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => â‚¬ 198,231 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => â‚¬ 94,853 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => â‚¬ 3,272 )

SORTED by richness

<?php
$objects               
= new ObjSorter($objects_array,'richness');
if (
$objects->sorted)
{
$objects_array  $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
?>

user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => â‚¬ 144,540 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => â‚¬ 198,231 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => â‚¬ 219,078 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => â‚¬ 3,272 )
user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => â‚¬ 302,352 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => â‚¬ 677,180 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => â‚¬ 763,860 )
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => â‚¬ 899,970 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => â‚¬ 94,853 )

Simulated wrong property request ( dumb property )

<?php
$objects               
= new ObjSorter($objects_array,'dumb property');
if (
$objects->sorted)
{
$objects_array  $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
else echo 
'DUMB ERROR';
?>

DUMB ERROR
2008-12-28 19:37:48
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
To sort reliably on more than one "column" in database-style arrays, handle this within your cmp function where the first field to be sorted returns 0:

<?php

function cmp($a$b){
   
 if(
$a[field_1] == $b[field_1]){

  if(
$a[field_2] == $b[field_2]){

   return 
0;

  }

  elseif(
$a[field_2] > $b[field_2]){

   return -
1;

  }

  elseif(
$a[field_2] < $b[field_2]){

   return 
1;

  }

 }

 elseif(
$a[field_1] > $b[field_1]){

  return -
1;

 }

 elseif(
$a[field_1] < $b[field_1]){

  return 
1;

 }

}

?>

Sorting by doing multiple passes does not seem to be reliable.
2009-01-12 05:14:39
http://php5.kiev.ua/manual/ru/function.usort.html
If you need to use usort with a key in the calling method, I wrote this as a utility:
<?php

function usort_comparison($obj$method$key) {
   
$usorter = &new Usort($obj$method$key);
    return array(
$usorter"sort");
}

class 
Usort {
    function 
__construct($obj$method$key) {
       
$this->obj $obj;
       
$this->method $method;
       
$this->key $key;
    }
    function 
sort($a$b) {
        return 
call_user_func_array(array($this->obj$this->method), array($a$b$this->key));
    }
}

?>

<?php

require_once("util/usort.php");

class 
Foo {
   
$items = array(FooBar(13), FooBar(2));
    public function 
sorter() {
       
usort($this-itemsusort_comparison("Foo""_cmp""item"));
    }

    public static function 
_cmp($a$b$key) {
         return 
strcasecmp($a->$key$b->$key);
    }

}

class 
FooBar {
    public 
$item;
    function 
__construct($val) {
       
$this->item $val;
    }
}

?>

~ simple example... but in the way I need to use it was the key was used in a switch statement to choose the different member of the object to compare against dynamically (as in, sort by x or y or z)
2009-03-28 14:25:32
http://php5.kiev.ua/manual/ru/function.usort.html
I wrote a wrapper for usort that lets you use something similar to an SQL ORDER BY clause. It can sort arrays of associative arrays and arrays of objects and I think it would work with some hybrid case.

Example of how the function works:

<?php
$testAry 
= array(
  array(
'a' => 1'b' => 2'c' => 3),
  array(
'a' => 2'b' => 1'c' => 3),
  array(
'a' => 3'b' => 2'c' => 1),
  array(
'a' => 1'b' => 3'c' => 2),
  array(
'a' => 2'b' => 3'c' => 1),
  array(
'a' => 3'b' => 1'c' => 2)
);

Utility::orderBy($testAry'a ASC, b DESC');

//Result:
$testAry = array(
  array(
'a' => 1'b' => 3'c' => 2),
  array(
'a' => 1'b' => 2'c' => 3),
  array(
'a' => 2'b' => 3'c' => 1),
  array(
'a' => 2'b' => 1'c' => 3),
  array(
'a' => 3'b' => 2'c' => 1),
  array(
'a' => 3'b' => 1'c' => 2)
);
?>

To sort an array of objects you would do something like:
Utility::orderBy($objectAry, 'getCreationDate() DESC, getSubOrder() ASC');

This would sort an array of objects that have methods getCreationDate() and getSubOrder().

Here is the function:

<?php
class Utility {
   
/*
    * @param array $ary the array we want to sort
    * @param string $clause a string specifying how to sort the array similar to SQL ORDER BY clause
    * @param bool $ascending that default sorts fall back to when no direction is specified
    * @return null
    */
   
public static function orderBy(&$ary$clause$ascending true) {
       
$clause str_ireplace('order by'''$clause);
       
$clause preg_replace('/\s+/'' '$clause);
       
$keys explode(','$clause);
       
$dirMap = array('desc' => 1'asc' => -1);
       
$def $ascending ? -1;

       
$keyAry = array();
       
$dirAry = array();
        foreach(
$keys as $key) {
           
$key explode(' 'trim($key));
           
$keyAry[] = trim($key[0]);
            if(isset(
$key[1])) {
               
$dir strtolower(trim($key[1]));
               
$dirAry[] = $dirMap[$dir] ? $dirMap[$dir] : $def;
            } else {
               
$dirAry[] = $def;
            }
        }

       
$fnBody '';
        for(
$i count($keyAry) - 1$i >= 0$i--) {
           
$k $keyAry[$i];
           
$t $dirAry[$i];
           
$f = -$t;
           
$aStr '$a[\''.$k.'\']';
           
$bStr '$b[\''.$k.'\']';
            if(
strpos($k'(') !== false) {
               
$aStr '$a->'.$k;
               
$bStr '$b->'.$k;
            }

            if(
$fnBody == '') {
               
$fnBody .= "if({$aStr} == {$bStr}) { return 0; }\n";
               
$fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";               
            } else {
               
$fnBody "if({$aStr} == {$bStr}) {\n" $fnBody;
               
$fnBody .= "}\n";
               
$fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";
            }
        }

        if(
$fnBody) {
           
$sortFn create_function('$a,$b'$fnBody);
           
usort($ary$sortFn);       
        }
    }
}
?>
2009-03-31 15:25:10
http://php5.kiev.ua/manual/ru/function.usort.html
Remember that functions inside of functions will become part of the global scope too. So, something like:

<?php
   
function foo($array) {
        function 
compare($a,$b) {
            return 
$a $b;
        }
       
usort($array"compare");
        return 
$array;
    }
   
    function 
bar($array) {
        function 
compare($a,$b) {
            return 
$a $b;
        }
       
usort($array"compare");
        return 
$array;
    }
   
   
foo($something);
   
bar($something_else);
?>
       
Will result in a fatal error because you're redeclaring 'compare'. This could be a little strange, e.g. for JavaScript programmers who expect functions in functions to become private outside of the parent scope.
2009-05-28 09:04:49
http://php5.kiev.ua/manual/ru/function.usort.html
If you ever have to sort a collection of objects on something like a string (name) present in every object, but want to keep the array of objects intact you might find this useful:

<?php
function naturalSortObjectArray($objectArray) {
        function 
naturalSortByName($a$b) {
            return 
strnatcmp($a->name$b->name);
        }
       
usort($objectArray"naturalSortByName");
        return 
$objectArray;
}
?>
2009-07-17 11:45:46
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
An even better implementation of osort [than my original, posted on 24-AUG-09 (since deleted)], allowing for multiple properties and directions.  With php 5.3.0 sorting by properties of an object becomes MUCH simpler.  Note that this uses anonymous functions / closures. Might find reviewing the php docs on that useful.  Look below for examples for previous version of php.

<?php
function osort(&$array$props)
{
    if(!
is_array($props))
       
$props = array($props => true); 
       
   
usort($array, function($a$b) use ($props) {
        foreach(
$props as $prop => $ascending)
        {
            if(
$a->$prop != $b->$prop)
            {
                if(
$ascending)
                    return 
$a->$prop $b->$prop : -1;
                else
                    return 
$b->$prop $a->$prop : -1;
            }
        }
        return -
1//if all props equal       
   
});   
}
?>

Usage:

<?php
osort
($items, array("Color" => true"Size" => false));
//or
osort($items"Color");
?>
2009-08-27 17:31:16
http://php5.kiev.ua/manual/ru/function.usort.html
Another way to compare object is to have a compare static function in the class with reccursion ability and have globals or static variables who save the state of comparison, and the order.

It could be a good idea to have a variable with comparison functions name (with the sorting : numeric, alphanumeric, inverse).

<?php
interface Comparable{static function compare($a$b);}
class 
myObj implements Comparable{
        var 
$var1; var $var2; var $var3;
        function 
__construct($v1$v2$v3){
               
$this->var1=$v1$this->var2=$v2$this->var3=$v3;
        }
        public function 
__toString() {
                return 
"v1 ".$this->var1." v2 ".$this->var2." v3 ".$this->var3;
        }
        static function 
compare($a$b){
               
$sort=$GLOBALS['sorts'][$GLOBALS['sort']];
                echo 
"$sort\n";
                if(
$a->$sort == $b->$sort){
                        if(
$GLOBALS['sorts'][$GLOBALS['sort']+1]){
                               
$GLOBALS['sort']++;
                               
$rescall_user_func(array('myObj''compare'), $a$b);
                               
$GLOBALS['sort']=0; return $res;
                        }
                       
$GLOBALS['sort']=0; return 0;
                }
               
$GLOBALS['sort']=0;
                if(
$a->$sort $b->$sort)
                        return 
1;
                return -
1;
        }
}

$objects = array(new myObj("1""2""3"), new myObj("2""2""2"), new myObj("1""3""4"));

/* Tests */
$sorts=Array('var1''var2''var3'); $sort 0usort($objects, array('myObj''compare')); echo ("var1 var2 var3\n"); foreach($objects as $o)echo $o."\n";
$sorts=Array('var2''var3''var1'); $sort 0usort($objects, array('myObj''compare')); echo ("\nvar2 var3 var1\n"); foreach($objects as $o)echo $o."\n";
$sorts=Array('var2''var1''var3'); $sort 0usort($objects, array('myObj''compare')); echo ("\nvar2 var1 var3\n"); foreach($objects as $o)echo $o."\n";

?>
2010-04-10 14:37:09
http://php5.kiev.ua/manual/ru/function.usort.html
I'd like to share with the community my function for sorting an array of arrays or objects containing associative data. This could be used, for example, with a MySQL result.

<?php
function sort_by($field, &$arr$sorting=SORT_ASC$case_insensitive=true){
    if(
is_array($arr) && (count($arr)>0) && ( ( is_array($arr[0]) && isset($arr[0][$field]) ) || ( is_object($arr[0]) && isset($arr[0]->$field) ) ) ){
        if(
$case_insensitive==true$strcmp_fn "strnatcasecmp";
        else 
$strcmp_fn "strnatcmp";

        if(
$sorting==SORT_ASC){
           
$fn create_function('$a,$b''
                if(is_object($a) && is_object($b)){
                    return '
.$strcmp_fn.'($a->'.$field.', $b->'.$field.');
                }else if(is_array($a) && is_array($b)){
                    return '
.$strcmp_fn.'($a["'.$field.'"], $b["'.$field.'"]);
                }else return 0;
            '
);
        }else{
           
$fn create_function('$a,$b''
                if(is_object($a) && is_object($b)){
                    return '
.$strcmp_fn.'($b->'.$field.', $a->'.$field.');
                }else if(is_array($a) && is_array($b)){
                    return '
.$strcmp_fn.'($b["'.$field.'"], $a["'.$field.'"]);
                }else return 0;
            '
);
        }
       
usort($arr$fn);
        return 
true;
    }else{
        return 
false;
    }
}
?>
2010-05-06 07:03:29
http://php5.kiev.ua/manual/ru/function.usort.html
strcmp (or strcasecmp) can be used as a callback function for usort. It will cast your comparison values to string. Thus, you can implement a __toString() method into your classes and use usort without creating a callback function:

<?php
class Foo {
   private 
$a;
   private 
$b;

   public function 
__construct($a$b) {
     
$this->$a;
     
$this->$b;
   }

   public function 
__toString() {
      return (string)
$this->a;
   }
}

$foo = array(new Foo('t''b'), new Foo('a''c'), new Foo('g''d'));

print_r($foo);

usort($foo'strcasecmp');

print_r($foo);
?>
2010-08-01 14:06:07
http://php5.kiev.ua/manual/ru/function.usort.html
This comment is just to help backward compatibility.

I needed to have a foreach loop using reference just before using the usort function on the same array that was used in the foreach.

Like this:
<?php
public function sortByTitle()
{
        if(empty(
$this->_arrSubCat))
            return 
false;
       
        foreach(
$this->_arrSubCat as &$cat)
           
$cat->sortByTitle();
       
       
usort($this->_arrSubCat'strcasecmp');
}
?>

I had this strange bug where the last object of the $this->_arrSubCat array before the sort was alway replaced/overwrited with his string value.

On my machine (PHP 5.3), I had no problem, but when I placed the code on another server, my code crashed with a fatal error (Because I was using a string as an object later in the code)

The solution I found is really simple, and avoid the array to have a reference declared in memory while running the sort function. Just add an unset($cat):

<?php
public function sortByTitle()
{
        if(empty(
$this->_arrSubCat))
            return 
false;
       
        foreach(
$this->_arrSubCat as &$cat)
           
$cat->sortByTitle();
       
        unset(
$cat); //No more problem because of the foreach &cat reference.   
       
usort($this->_arrSubCat'strcasecmp');
}
?>

It took me an hour an a half to locate the bug, hope it will save someone some time !
2010-09-29 17:23:36
http://php5.kiev.ua/manual/ru/function.usort.html
[The second version of a function I wrote], just a little cleaner to use, since the usort call is now folded into the custom 'usortByArrayKey' function.

Seems like this is a popular problem - sorting an array of arrays by the keys of sub-arrays, so I'll go ahead and throw in an approach I haven't seen anyone mention yet. It only works since PHP 5.3 because that's when anonymous functions got added to the language. 

<?php 
function usortByArrayKey(&$array$key$asc=SORT_ASC) { 
   
$sort_flags = array(SORT_ASCSORT_DESC); 
    if(!
in_array($asc$sort_flags)) throw new InvalidArgumentException('sort flag only accepts SORT_ASC or SORT_DESC'); 
   
$cmp = function(array $a, array $b) use ($key$asc$sort_flags) { 
        if(!
is_array($key)) { //just one key and sort direction 
           
if(!isset($a[$key]) || !isset($b[$key])) { 
                throw new 
Exception('attempting to sort on non-existent keys'); 
            } 
            if(
$a[$key] == $b[$key]) return 0
            return (
$asc==SORT_ASC xor $a[$key] < $b[$key]) ? : -1
        } else { 
//using multiple keys for sort and sub-sort 
           
foreach($key as $sub_key => $sub_asc) { 
               
//array can come as 'sort_key'=>SORT_ASC|SORT_DESC or just 'sort_key', so need to detect which 
               
if(!in_array($sub_asc$sort_flags)) { $sub_key $sub_asc$sub_asc $asc; } 
               
//just like above, except 'continue' in place of return 0 
               
if(!isset($a[$sub_key]) || !isset($b[$sub_key])) { 
                    throw new 
Exception('attempting to sort on non-existent keys'); 
                } 
                if(
$a[$sub_key] == $b[$sub_key]) continue; 
                return (
$sub_asc==SORT_ASC xor $a[$sub_key] < $b[$sub_key]) ? : -1
            } 
            return 
0
        } 
    };
   
usort($array$cmp);
}; 
?>

Examples: 
1) Sort a multi-dimensional array by a single key, from least to greatest: 
    usortByArrayKey($resultset, 'order_id'); 

2) Sort a multi-dimensional array by a single key, from greatest to least: 
    usortByArrayKey($resultset, 'purchase_amount', SORT_DESC); 

3) Sort a multi-dimensional array first by one key, but then by a different key when the first one is equal, both from least to greatest: 
    usortByArrayKey($resultset, array('product_id', 'price')); 

4) Sort a multi-dimensional array by two different keys from least to greatest, and then a third from greatest to least if the first two keys map to the equal values: 
    usortByArrayKey($resultset, array('product_id', 'customer_id', 'date'=>SORT_DESC)); 

5) Sort a multi-dimensional array by multiple keys, all from greatest to least: 
    usortByArrayKey($resultset, array('product_id', 'price'), SORT_DESC);

One word of caution, since SORT_ASC and SORT_DESC have actual int values of 4 and 3, respectively, if you need to sort a multi-dimensional array by keys 3 or 4, and you're using an array to pass in your keys, you MUST specify your sort flags (e.g. array(3 => SORT_ASC,...)) to prevent unexpected behavior, instead of relying on the function's second parameter as your default sort flag.
2011-06-13 13:42:03
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
Sorting a multidimensional array by a subkey seem to be one of the bigger challenges when using usort. At least if one want the key to be dynamic. For anyone interested this code seemed to work rather well for me:

<?php

usort
($array,array(new cmp($key), "cmp__"));

class 
cmp {
    var 
$key;
    function 
__construct($key) {
       
$this->key $key;
    }
   
    function 
cmp__($a,$b) {
       
$key $this->key;
        if (
$a[$key] == $b[$key]) return 0;
        return ((
$a[$key] > $b[$key]) ? : -1);
    }
}

?>
2011-06-28 14:12:43
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
<?php
/**
 * Sort array of objects by field.
 *
 * @param array $objects Array of objects to sort.
 * @param string $on Name of field.
 * @param string $order (ASC|DESC)
 */
function sort_on_field(&$objects$on$order 'ASC') {
   
$comparer = ($order === 'DESC')
        ? 
"return -strcmp(\$a->{$on},\$b->{$on});"
       
"return strcmp(\$a->{$on},\$b->{$on});";
   
usort($objectscreate_function('$a,$b'$comparer));
}
?>
2011-07-12 20:55:13
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
this is a new multisort function for sorting on multiple subfield like it will be in sql : 'ORDER BY field1, field2'
number of sort field is undefined
<?php

$array
[] = array('soc' => 3'code'=>1);
$array[] = array('soc' => 2'code'=>1);
$array[] = array('soc' => 1'code'=>1);
$array[] = array('soc' => 1'code'=>1);
$array[] = array('soc' => 2'code'=>5);
$array[] = array('soc' => 1'code'=>2);
$array[] = array('soc' => 3'code'=>2);

//usage
print_r(multiSort($array'soc''code'));

function 
multiSort() {
   
//get args of the function
   
$args func_get_args();
   
$c count($args);
    if (
$c 2) {
        return 
false;
    }
   
//get the array to sort
   
$array array_splice($args01);
   
$array $array[0];
   
//sort with an anoymous function using args
   
usort($array, function($a$b) use($args) {

       
$i 0;
       
$c count($args);
       
$cmp 0;
        while(
$cmp == && $i $c)
        {
           
$cmp strcmp($a$args$i ] ], $b$args$i ] ]);
           
$i++;
        }

        return 
$cmp;

    });

    return 
$array;

}
?>

output:
Array
(
    [0] => Array
        (
            [soc] => 1
            [code] => 1
        )

    [1] => Array
        (
            [soc] => 1
            [code] => 1
        )

    [2] => Array
        (
            [soc] => 1
            [code] => 2
        )

    [3] => Array
        (
            [soc] => 2
            [code] => 1
        )

    [4] => Array
        (
            [soc] => 2
            [code] => 5
        )

    [5] => Array
        (
            [soc] => 3
            [code] => 1
        )

    [6] => Array
        (
            [soc] => 3
            [code] => 2
        )

)
2011-09-13 09:09:10
http://php5.kiev.ua/manual/ru/function.usort.html
sort multi-dimentional arrays in class with usort

<?php
class ArraySort
{
    private 
$arr = array();

    public function 
__construct($arr)
    {
       
$this->arr $arr;
    }

    public function 
doSort()
    {
       
$cmp = function($a$b)
        {
           
//Do Some Comparation
       
}
        if(
is_array($this->arr))
        {
           
usort($this->arr$cmp);
        }
        return 
$this->arr;
    }
}
?>
2011-12-04 22:58:38
http://php5.kiev.ua/manual/ru/function.usort.html
I needed a sort method that would sort strings but take note of any numbers and would compare them as number. I also want to ignore any non alphanumerical characters.

Eg.
Slot 1 Example
Slot 10 Example
Slot 2 Example

Should infact be
Slot 1 Example
Slot 2 Example
Slot 10 Example

<?php
function sort_with_numbers($a $b) {
   
$a explode(' ',$a);
   
$b explode(' ',$b);
   
$size min(count($a), count($b));
    for(
$index =0$index $size; ++$index) {
       
$a1 ereg_replace("[^A-Za-z0-9]""",$a[$index]);
       
$b1 ereg_replace("[^A-Za-z0-9]""",$b[$index]);
       
$equal 0;
        if (
is_numeric($a1) && is_numeric($b1)) {
           
$equal $a1 $b1;
        } else {
           
$equal strcasecmp($a1,$b1);
        }
        if (
$equal 0) {
            return -
1;
        }
        if (
$equal 0) {
            return 
1;
        }
    }
    return 
count($a) - count($b);   
}
?>
2012-02-04 17:58:08
http://php5.kiev.ua/manual/ru/function.usort.html
When trying to do some custom sorting with objects and an anonymous function it wasn't entirely clear how this usort function works. I think it probably uses a quicksort in the background. Basically it actually moves the $b variable up or down in respect to the $a variable. It does NOT move the $a variable inside the callback function. This is key to getting your logic right in the comparisons.

If you return -1 that moves the $b variable down the array, return 1 moves $b up the array and return 0 keeps $b in the same place. 

To test I cut down my code to sorting a simple array from highest priority to lowest.

<?php
$priorities 
= array(58373);

usort($priorities, function($a$b)
{
    if (
$a == $b)
    {
        echo 
"a ($a) is same priority as b ($b), keeping the same\n";
        return 
0;
    }
    else if (
$a $b)
    {
        echo 
"a ($a) is higher priority than b ($b), moving b down array\n";
        return -
1;
    }
    else {
        echo 
"b ($b) is higher priority than a ($a), moving b up array\n";               
        return 
1;
    }
});

echo 
"Sorted priorities:\n";
var_dump($priorities);
?>

Output:

b (8) is higher priority than a (3), moving b up array
b (5) is higher priority than a (3), moving b up array
b (7) is higher priority than a (3), moving b up array
a (3) is same priority as b (3), keeping the same
a (8) is higher priority than b (3), moving b down array
b (8) is higher priority than a (7), moving b up array
b (8) is higher priority than a (5), moving b up array
b (8) is higher priority than a (3), moving b up array
a (5) is higher priority than b (3), moving b down array
a (7) is higher priority than b (5), moving b down array

Sorted priorities:
array(5) {
  [0]=> int(8)
  [1]=> int(7)
  [2]=> int(5)
  [3]=> int(3)
  [4]=> int(3)
}
2012-03-30 00:56:45
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
The usort function actually moves $b up when the callback function returns both 0 and 1.  If you want to preserve the original order in the array, return 1 when $a == $b instead of 0.  Try this code below to see how usort alters the order of the original array when all values are the same.

<?php
class TestObj {
    private 
$name;
    private 
$id;

    function 
TestObj($name$id) {
       
$this->name $name;
       
$this->id $id;
    }

    static function 
cmp_obj($a$b) {
       
$al strtolower($a->name);
       
$bl strtolower($b->name);
        if (
$al == $bl) {
            return 
0// return 1 if you don't want $b to go in front of $a
       
}
        return (
$al $bl) ? +: -1;
    }
}

$a[] = new TestObj("a"1);
$a[] = new TestObj("a"2);
$a[] = new TestObj("a"3);

var_dump($a);
usort($a, array("TestObj""cmp_obj"));
var_dump($a);
?>
2012-07-07 00:16:20
http://php5.kiev.ua/manual/ru/function.usort.html
Needed to sort an array of objects based on multiple properties. (ie: Group, then Last Name, then First Name) Doing this in multiple usorts fails because the second usort ends up shuffling the results of the previous usort because order is undefined when criteria are equal. Ended up writing a function that builds a comparison operator by nesting ternary operators for each field, then using that function in usort(). Hopefully it's of use to someone else.

<?php
/*
 * Sorts an array of objects by a list of properties.
 * Each property can have the following options:
 *   'property' can be either a public variable or a method().
 *   'order' can be ASC or DESC
 *   'comparer' can be string, number, or date
 * 
 * Example:
 * sortObjectsByProperties($objects, array(
 *       array('property'=>'getPrice()', order=>'ASC', 'comparer'=>'number'),
 *       array('property'=>'getName()', order=>'DESC', 'comparer'=>'string'),
 *       array('property'=>'created_date', order=>'ASC', 'comparer'=>'date'),
 *       array('property'=>'id', order=>'ASC', 'comparer'=>'number'),
 *   ));
 * 
 * @author Tyler Chamberlain
 */
function sortObjectsByProperties(&$objects$fields) {
       
$comparerFunctionString "";
        foreach (
$fields as $field) {
            if (
$field['comparer'] == 'number') {
               
$comparerFunction "(\$a->{$field['property']} == \$b->{$field['property']} ? 0 : (\$a->{$field['property']} > \$b->{$field['property']} ? 1 : -1))";
            } elseif (
$field['comparer'] == 'date') {
               
$comparerFunction "(strtotime(\$a->{$field['property']}) > strtotime(\$b->{$field['property']}) ? 1 : -1)";
            } else {
               
$comparerFunction "strcasecmp(\$a->{$field['property']},\$b->{$field['property']})";
            }
            if (
$field['order'] === 'DESC') { $comparerFunction "-".$comparerFunction; }
           
$comparerFunctionString .= "$comparerFunction != 0 ? $comparerFunction : (";
        }
       
$comparer "return ($comparerFunctionString 0 )".str_repeat(")"sizeof($fields)).";";
       
usort($objectscreate_function('$a,$b'$comparer)); 
}
?>
2013-02-21 23:04:32
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
As the documentation says, the comparison function needs to return an integer that is either "less than, equal to, or greater than zero". There is no requirement to restrict the value returned to -1, 0, 1.

<?php
usort
($array, function($a$b) {
    if(
$a->integer_property $b->integer_property) {
        return 
1;
    }
    elseif(
$a->integer_property $b->integer_property) {
        return -
1;
    }
    else {
        return 
0;
    }
});
?>

can be simplified to

<?php
usort
($array, function($a$b) {
    return 
$a->integer_property $b->integer_property;
});
?>

This of course applies to any comparison function that calculates an integer "score" for each of its arguments to decide which is "greater".
2013-04-09 01:30:19
http://php5.kiev.ua/manual/ru/function.usort.html
If you want to sort the time based array, then this will be helpfull.

function timesort($array){
            usort($array, function($a, $b)
            {
                $a=strtotime($a);
                $b=strtotime($b);
               
                if ($a == $b)
                {
                    return 0;
                }
                else if ($a < $b)
                {
                    return -1;
                }
                else {
                    return 1;
                }
            });
}

Input:

$time_array=Array
(
    [1] => 10:00AM
    [2] => 09:00AM
    [3] => 02:00PM
    [4] => 11:00AM
)

Output: 
print_r(timesort($time_array));
Array
(
    [0] => 09:00AM
    [1] => 10:00AM
    [2] => 11:00AM
    [3] => 02:00PM
)
2013-08-07 11:37:57
http://php5.kiev.ua/manual/ru/function.usort.html
Автор:
usort returns null when the sorting function is not (yet) defined. The function has to be defined before usort is called, afterwards doesn't work.
2013-12-09 09:57:20
http://php5.kiev.ua/manual/ru/function.usort.html
Below is a variation on Example #4 that implements a multi-key natural sort on an associative array and can be called in such a way as to allow reversing the sort order and/or making the comparison case insensitive on a key by key basis.

Test code is included in the file – run it from the command line with: php sortUtils.php

<?php
/**
 *    sortUtils.php
*/

/**
 *    mknatsort() - Multi-Key Natural Sort for associative arrays
 *
 *    Uses the usort() function to perform a natural sort on a multi-dimensional
 *    array on multiple keys. Optionally specifying the sort order for each key
 *    and/or ignoring the case for each key value.
 *
 *    @param array $data_array The array to be sorted.
 *    @param mixed $keys The list of keys to be sorted by. This may be a single
 *        key or an array of keys
 *    @param boolean $reverse Specify whether or not to reverse the sort order. If
 *        there are multiple keys then $reverse may be an array of booleans - one
 *        per key.
 *    @param boolean $ignorecase Specify whether or not to ignore the case when
 *        comparing key values.reverse the sort order. If there are multiple keys
 *        then $ignorecase may be an array of booleans - one per key.
*/
function mknatsort ( &$data_array$keys$reverse=false$ignorecase=false ) {
   
// make sure $keys is an array
   
if (!is_array($keys)) $keys = array($keys);
   
usort($data_arraysortcompare($keys$reverse$ignorecase) );
}

function 
sortcompare($keys$reverse=false$ignorecase=false) {
    return function (
$a$b) use ($keys$reverse$ignorecase) {
       
$cnt=0;
       
// check each key in the order specified
       
foreach ( $keys as $key ) {
           
// check the value for ignorecase and do natural compare accordingly
           
$ignore is_array($ignorecase) ? $ignorecase[$cnt] : $ignorecase;
           
$result $ignore strnatcasecmp ($a[$key], $b[$key]) : strnatcmp($a[$key], $b[$key]);
           
// check the value for reverse and reverse the sort order accordingly
           
$revcmp is_array($reverse) ? $reverse[$cnt] : $reverse;
           
$result $revcmp ? ($result * -1) : $result;
           
// the first key that results in a non-zero comparison determines
            // the order of the elements
           
if ( $result != ) break;
           
$cnt++;
        }
        return 
$result;
    };
// end sortcompare()

// test code that will be skipped if this is included in the web environment
// test with: php sortUtils.php from the command line
$sapi_type php_sapi_name();
if (
substr($sapi_type03) == 'cli') {

   
// the following shows several examples of usage and the resulting output.
   
$test[] = array('Status'=>'In Progress''comment'=>'This looks good.''user_name'=>'John Doe''date_modified'=>'06/13/2014 11:20 AM''role'=>'Senior Account Manager');
   
$test[] = array('Status'=>'In Progress''comment'=>'This looks good, please approve.''user_name'=>'John Doe''date_modified'=>'06/13/2014 11:19 AM''role'=>'Account Manager');
   
$test[] = array('Status'=>'In Progress''comment'=>'This looks good.''user_name'=>'Jane Smith''date_modified'=>'06/13/2014 11:19 AM''role'=>'Senior Account Manager');
   
$test[] = array('Status'=>'Returned''comment'=>'There is not enough informartion.  Please add the following.''user_name'=>'John Doe''date_modified'=>'06/13/2014 11:15 AM''role'=>'Account Manager');
   
$test[] = array('Status'=>'In Progress''comment'=>'I am currently reviewing this.''user_name'=>'John Doe''date_modified'=>'06/13/2014 11:14 AM''role'=>'Account Manager');
    echo 
"Original array: ";
   
print_r($test);

    echo 
"Sorted on date_modified: ";
   
mknatsort($test, array('date_modified') );
   
print_r($test);

    echo 
"Sorted on role(reversed) & date_modified: ";
   
mknatsort($test, array('role','date_modified'),array(true,false) );
   
print_r($test);

    echo 
"Sorted on role & date_modified(reversed): ";
   
mknatsort($test, array('role','date_modified'),array(false,true) );
   
print_r($test);
}

?>
2014-12-03 17:10:36
http://php5.kiev.ua/manual/ru/function.usort.html
I see many people here (including the official examples) write their callbacks rather clumsily like this:

<?php
function($a$b) {
  if (
$a === $b) {
    return 
0;
  } elseif (
$a $b) {
    return -
1
  } else {
    return 
1;
  }
}
?>

Or if they are a bit more clever:

<?php
function($a$b) {

  if (
$a === $b) {
    return 
0;
  } else {
    return 
$a $b ? -1;
  }
}
?>

But this can by simplified further to:

<?php
function($a$b) {
  return 
$a $b;
}
?>
2015-07-17 02:13:27
http://php5.kiev.ua/manual/ru/function.usort.html
Now, in php 7, we can use the spaceship operator. For example lest sort array of words from element string length:

<?php
$sampleArray 
= ['one''two'free', 'fore', 'five];

usort($sampleArray, function($a$b) {
      return 
strlen($a) <=> strlen($b);
});
2016-01-31 19:26:34
http://php5.kiev.ua/manual/ru/function.usort.html
You can also sort multi-dimensional array for multiple values like as

<?php 
$arr 
= [
    [
       
"name"=> "Sally",
       
"nick_name"=> "sal",
       
"availability"=> "0",
       
"is_fav"=> "0"
   
],
    [
       
"name"=> "David",
       
"nick_name"=> "dav07",
       
"availability"=> "0",
       
"is_fav"=> "1"
   
],
    [
       
"name"=> "Zen",
       
"nick_name"=> "zen",
       
"availability"=> "1",
       
"is_fav"=> "0"
   
],
    [
       
"name"=> "Jackson",
       
"nick_name"=> "jack",
       
"availability"=> "1",
       
"is_fav"=> "1"
   
],
    [
       
"name"=> "Rohit",
       
"nick_name"=> "rod",
       
"availability"=> "0",
       
"is_fav"=> "0"
   
],

];

usort($arr,function($a,$b){
   
$c $b['is_fav'] - $a['is_fav'];
   
$c .= $b['availability'] - $a['availability'];
   
$c .= strcmp($a['nick_name'],$b['nick_name']);
    return 
$c;
});

print_r($arr);
?>

Output:

Array
(
    [0] => Array
        (
            [name] => Jackson
            [nick_name] => jack
            [availability] => 1
            [is_fav] => 1
        )

    [1] => Array
        (
            [name] => David
            [nick_name] => dav07
            [availability] => 0
            [is_fav] => 1
        )

    [2] => Array
        (
            [name] => Zen
            [nick_name] => zen
            [availability] => 1
            [is_fav] => 0
        )

    [3] => Array
        (
            [name] => Rohit
            [nick_name] => rod
            [availability] => 0
            [is_fav] => 0
        )

    [4] => Array
        (
            [name] => Sally
            [nick_name] => sal
            [availability] => 0
            [is_fav] => 0
        )

)
2016-02-19 14:12:57
http://php5.kiev.ua/manual/ru/function.usort.html
Just wanted to show off the beauty of PHPs spaceship operator in this use case.

<?php // tested on PHP 7.1
$a = [2136547];
$asc $desc $a;
usort($asc, function (int $aint $b) { return ($a <=> $b); });
usort($desc, function (int $aint $b) { return -($a <=> $b); });
print_r([ $a$asc$desc ]);

/**
 * Getting ahead of myself but... If arrow function syntax was possible:
 * usort($asc, (int $a, int $b) => ($a <=> $b));
 * usort($desc, (int $a, int $b) => -($a <=> $b));
 */
?>
2016-12-16 21:56:23
http://php5.kiev.ua/manual/ru/function.usort.html
to sort with numeric and empty values  and have the smallest on top:
<?php
    usort
($list, function($a$b) {
        if( 
$a == null && $b != null ) return 1;
        if( 
$a != null && $b == null ) return -1;
        return 
$a $b : -1;
    });
?>
returns
1
2
3
null
null
null
2017-01-14 20:50:44
http://php5.kiev.ua/manual/ru/function.usort.html
to sort with numeric and empty values  and have the smallest on top:
<?php
    usort
($list, function($a$b) {
        if( 
$a == null && $b != null ) return 1;
        if( 
$a != null && $b == null ) return -1;
        return 
$a $b : -1;
    });
?>
returns
1
2
3
null
null
null
2017-01-14 20:51:17
http://php5.kiev.ua/manual/ru/function.usort.html

    Поддержать сайт на родительском проекте КГБ