uasort

Sorts an array by value using a custom comparison callback while preserving keys.

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

Parameters

ParameterTypeDescription
$arrayarrayThe array to sort. Passed by reference; key/value associations are preserved.
$callbackcallableComparison function callback(mixed $a, mixed $b): int receiving two values. Must return an integer less than, equal to, or greater than zero when $a is respectively less than, equal to, or greater than $b.

Return value

trueAlways returns true. The array is sorted in place through the reference.

Errors

Nothing is thrown by uasort itself, but any Throwable raised inside the callback propagates and aborts the sort. A callback that is not callable raises a TypeError.

Changelog

  • PHP 8.2The return type is true now; previously it was bool.
  • PHP 8.0If the callback expects a parameter to be passed by reference, an E_WARNING is emitted. Equal elements also keep their original order (stable sort) as of 8.0.

uasort is usort that keeps the keys. You supply a comparison callback that receives two values and returns a negative number, zero, or a positive number; PHP orders the array accordingly and every value stays paired with its original key.

When to reach for it

Reach for it whenever an associative array needs an ordering the built-in flags cannot express and the keys carry meaning: user IDs mapped to records that should sort by signup date, product SKUs mapped to rows that sort by price then name, a config map ordered by a priority field. The spaceship operator makes the callback a one-liner — fn($a, $b) => $a['price'] <=> $b['price'] — and chaining with ?: gives you tie-breakers.

What trips people up

The callback must return an integer. Returning a boolean is the most common bug: fn($a, $b) => $a > $b yields true/false, which cast to 1 and 0, so "less than" is never expressed and the result is subtly wrong. The same applies to float differences — $a - $b on prices like 0.4 truncates to 0 and the items are treated as equal. Always use <=>.

The sort is stable as of PHP 8.0, so equal elements keep their input order — useful, but it means a comparison returning 0 silently freezes the original order rather than being arbitrary.

Example

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

When to use it

  • Order an id-keyed map of user records by their signup timestamp for a dashboard list.
  • Sort a SKU-keyed product map by price, falling back to name for ties.
  • Rank a keyed set of search results by a computed score without losing the result IDs.

Frequently asked questions

What is the difference between usort and uasort?

Both sort with a custom callback over values, but usort discards the keys and renumbers from 0 while uasort preserves the key/value associations. Use uasort when the keys identify the rows.

Why is my uasort result in the wrong order?

Almost always because the callback returns a bool or a truncated float instead of an int. Use the spaceship operator, $a <=> $b, which returns -1, 0 or 1.

Is uasort stable in PHP 8?

Yes. As of PHP 8.0 elements whose comparison returns 0 keep their original relative order, so you can layer sorts by calling uasort repeatedly from the least significant key.

More examples

Multi-level sort with a tie-breaker

Prices sort first, so b comes out on top. The two items at price 10 tie, the ?: falls through to strcmp, and 'argon' beats 'zinc' — giving b, c, a.

Example · php
<?php
$items = [
    'a' => ['price' => 10, 'name' => 'zinc'],
    'b' => ['price' => 5,  'name' => 'iron'],
    'c' => ['price' => 10, 'name' => 'argon'],
];

uasort($items, fn($x, $y) =>
    ($x['price'] <=> $y['price']) ?: strcmp($x['name'], $y['name'])
);

foreach ($items as $k => $i) {
    echo "$k {$i['price']} {$i['name']}\n";
}

Boolean callback bug versus the spaceship operator

On PHP 8.3 and later the boolean callback emits "Deprecated: uasort(): Returning bool from comparison function is deprecated…" and PHP works around the missing "less than" answer by calling the callback a second time with the arguments swapped, so both lines print {"y":1,"z":2,"x":3}. Before 8.3 the boolean version could genuinely come out in the wrong order; the spaceship version is the only form that is both correct and deprecation-free.

Example · php
<?php
$src = ['x' => 3, 'y' => 1, 'z' => 2];

$bad = $src;
uasort($bad, fn($a, $b) => $a > $b);
echo 'bool callback: ', json_encode($bad), "\n";

$good = $src;
uasort($good, fn($a, $b) => $a <=> $b);
echo 'spaceship:     ', json_encode($good), "\n";

Discussion

  • Be the first to comment on this lesson.