usort
Sorts an array in place using a user-defined comparison callback, discarding the existing keys.
usort(array &$array, callable $callback): true- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$array | array | The array to sort. It is passed by reference and modified in place, so it must be a variable. |
$callback | callable | Comparison function with the signature callback(mixed $a, mixed $b): int. Return an integer less than zero if $a sorts before $b, zero if they are equal, greater than zero if $a sorts after $b. |
Return value
trueAlways returns true. The sorting happens in place on the array passed by reference.
Errors
Throws a TypeError if callback is not callable. Because array is by reference it must be a variable: passing a literal throws Error: usort(): Argument #1 ($array) could not be passed by reference at run time, while passing a function call's result only raises Notice: Only variables should be passed by reference and sorts a temporary that is then discarded. Neither case is a compile-time error.
Changelog
- PHP 8.2.0The return type is now true; previously it was bool.
- PHP 8.0.0The sort is now stable: elements the callback reports as equal keep their original relative order. Before 8.0 that order was undefined.
- PHP 8.0.0An E_WARNING is emitted if the callback declares its parameters by reference.
usort sorts an array by whatever rule you write, instead of by PHP's built-in value comparison. Reach for it whenever the ordering is not simply "smallest number or string first": sorting records by one of their fields, ordering by a custom priority list, sorting date strings that are not in a sortable format, or pushing a particular status to the top.
The callback receives two elements and must return a negative integer, zero, or a positive integer. The spaceship operator gives you all three at once: fn($a, $b) => $a['price'] <=> $b['price']. Swap the operands for descending order. To sort by several fields, compare arrays, which PHP compares element by element: [$a['dept'], $a['name']] <=> [$b['dept'], $b['name']].
The array is passed by reference and sorted in place, so usort returns true, not the sorted array. Reading the return value into a variable is a common beginner mistake.
What trips people up
- Returning a boolean such as
$a > $b.falsecasts to0, so "less than" and "equal" become indistinguishable and the result is wrong. - Returning a float.
0.4casts to0, so near values compare as equal. Return$a <=> $binstead of subtracting floats. - Expecting keys to survive. They do not.
Example
When to use it
- Sort order rows by total descending before rendering a table.
- Order search results by a relevance score you calculated yourself.
- Sort filenames by a date embedded in the name rather than alphabetically.
- Put tickets with priority 'urgent' first, then the rest by creation time.
Frequently asked questions
What is the difference between usort and uasort?
usort discards the array's keys and reindexes the result from 0, while uasort keeps each key attached to its value. Use uasort for associative arrays and usort for plain lists.
Does usort return the sorted array?
No. It sorts the array in place through a by-reference parameter and returns true (bool before PHP 8.2), so you read the result from the original variable, not from the return value.
Is usort stable in PHP 8?
Yes. Since PHP 8.0 all PHP sort functions are stable, so elements your callback reports as equal keep their original relative order. Before 8.0 that order was undefined and could change between versions.
More examples
Sort by a custom priority order
Prints 2, 3, 1. The callback maps each priority string to a number through a lookup table, so the array sorts by business importance instead of alphabetically (which would give low, normal, urgent).
<?php
$rank = ['urgent' => 0, 'normal' => 1, 'low' => 2];
$tickets = [
['id' => 1, 'priority' => 'low'],
['id' => 2, 'priority' => 'urgent'],
['id' => 3, 'priority' => 'normal'],
];
usort($tickets, fn($a, $b) => $rank[$a['priority']] <=> $rank[$b['priority']]);
echo implode(', ', array_column($tickets, 'id')), "\n";Sort by two fields at once
Prints eng/Ali, eng/Zoe, ops/Ada. Comparing two arrays with the spaceship operator compares them position by position, so department decides first and name breaks the tie — no nested if statements needed.
<?php
$staff = [
['dept' => 'ops', 'name' => 'Ada'],
['dept' => 'eng', 'name' => 'Zoe'],
['dept' => 'eng', 'name' => 'Ali'],
];
usort($staff, fn($a, $b) =>
[$a['dept'], $a['name']] <=> [$b['dept'], $b['name']]);
foreach ($staff as $p) {
echo $p['dept'], '/', $p['name'], "\n";
}usort loses keys, uasort keeps them
The first print_r shows [0 => 12, 1 => 9, 2 => 7]: the names are gone. The second shows [bob => 12, carol => 9, alice => 7]. Same ordering, but only uasort keeps the association between key and value.
<?php
$scores = ['carol' => 9, 'alice' => 7, 'bob' => 12];
$a = $scores;
usort($a, fn(int $x, int $y): int => $y <=> $x);
print_r($a);
$b = $scores;
uasort($b, fn(int $x, int $y): int => $y <=> $x);
print_r($b);
Discussion