usort

Sorts an array in place using a user-defined comparison callback, discarding the existing keys.

Signature
usort(array &$array, callable $callback): true
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$arrayarrayThe array to sort. It is passed by reference and modified in place, so it must be a variable.
$callbackcallableComparison 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. false casts to 0, so "less than" and "equal" become indistinguishable and the result is wrong.
  • Returning a float. 0.4 casts to 0, so near values compare as equal. Return $a <=> $b instead of subtracting floats.
  • Expecting keys to survive. They do not.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

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).

Example · php
<?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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.