Arrays7 min readExamples run on PHP 8.5.10

uasort()

Learn how PHP 8.4 uasort() sorts an array in place with your own comparison callback while preserving key-to-value association, plus edge cases and pitfalls.

Signature

uasort(array &$array, callable $callback): true

Purpose

uasort() sorts an array in place by its values, using a comparison function that you write. Unlike usort(), it keeps every key attached to its value. That makes it the right choice for associative arrays where the keys carry meaning, such as user IDs, product codes or player names, and you only want to change the order in which the entries appear.

Signature

Parameters and defaults

  • $array is the array to sort. It is passed by reference, so the original variable is rewritten. There is no copy to capture; if you need the original order afterwards, copy the array first.
  • $callback receives two values from the array, $a and $b. It must return an integer that is less than zero, zero, or greater than zero when $a is considered respectively smaller than, equal to, or larger than $b.

Neither parameter has a default value. Both are required.

Return value and failure cases

Since PHP 8.2 the declared return type is true; before that it was bool. Either way the function always reports success, so checking the result is rarely useful. The sorted result lives in the array you passed in.

Passing something that is not an array, or something that is not callable, throws a TypeError. As of PHP 8.0, a callback that expects its parameters by reference triggers an E_WARNING. The function also resets the array's internal pointer to the first element.

Example 1: sorting scores while keeping names

The spaceship operator <=> is the simplest correct comparison for numbers and strings. The keys follow their values, and the return value is true.

Example
<?php
$scores = ['ana' => 82, 'ben' => 95, 'cy' => 70, 'di' => 88];
$result = uasort($scores, fn(int $a, int $b): int => $a <=> $b);
echo json_encode($scores, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
var_dump($result);
Output
{"cy":70,"ana":82,"di":88,"ben":95}
bool(true)

Example 2: sorting records by a field

The callback can look inside nested values. Swapping the operands ($b first) gives a descending order. Entries that compare as equal keep their original relative order, so p1 stays ahead of p3.

Example
<?php
$players = [
    'p1' => ['name' => 'Ava', 'points' => 30],
    'p2' => ['name' => 'Ben', 'points' => 45],
    'p3' => ['name' => 'Cara', 'points' => 30],
    'p4' => ['name' => 'Dev', 'points' => 50],
];
uasort($players, fn(array $a, array $b): int => $b['points'] <=> $a['points']);
echo json_encode(array_keys($players)), "\n";
Output
["p4","p2","p1","p3"]

Example 3: the float-return trap

The comparison result is converted to an integer. If you return a plain difference of floats, any fraction below one is truncated to 0, and those values are treated as equal. The first sort below leaves the order unchanged; the second, using <=>, sorts correctly.

Example
<?php
$prices = ['a' => 1.5, 'b' => 1.2, 'c' => 1.9];
$wrong = $prices;
uasort($wrong, fn(float $x, float $y) => $x - $y);
$right = $prices;
uasort($right, fn(float $x, float $y): int => $x <=> $y);
echo json_encode($wrong), "\n";
echo json_encode($right), "\n";
Output
{"a":1.5,"b":1.2,"c":1.9}
{"b":1.2,"a":1.5,"c":1.9}

Edge cases

  • Empty and single-element arrays are valid. The callback is never needed, and the function still returns true.
  • Stable ordering: members that compare as equal keep their original order. Before PHP 8.0 their relative order was undefined, so older code might have added its own tie-breaker.
  • Integer-like keys such as "10" are stored as integers by PHP. uasort() never renumbers them, so they stay as they were.
  • Mixed types are handled by whatever your callback does. Using <=> on mixed values follows PHP's normal comparison rules, which can surprise you, so compare like with like when you can.
  • Multiple criteria: chain comparisons with ?: or compare arrays, for example [$a['group'], $a['name']] <=> [$b['group'], $b['name']].

Common mistakes

  1. Expecting a return value to hold the sorted array. The function sorts the variable itself and returns true. Writing $sorted = uasort($data, ...) gives you a boolean, not an array.
  2. Returning a boolean or a float such as $a > $b or $a - $b. Return an integer from <=> instead.
  3. Using usort() when keys matter. usort() discards the keys and assigns fresh numeric ones. Use uasort() to preserve them, or uksort() to sort by the keys.
  4. Sorting by key by accident. The callback receives values, not keys. If the order depends on a key, use uksort(), or restructure the data.
  5. Forgetting the array is modified. Any other code relying on the earlier order will see the new order.
  6. Declaring callback parameters by reference. This emits a warning from PHP 8.0 onward. Take the values by value.
  • usort() sorts by value with a custom comparison but does not preserve keys.
  • uksort() sorts by key with a custom comparison.
  • asort() and arsort() sort by value with standard comparison and keep keys.

Recap

uasort() sorts values with your own comparison function and keeps each key paired with its value. The array is changed in place, the return value is always true, equal items keep their original order, and the callback should return an integer, ideally from <=>.

Tested examples

Sort scores ascending while keeping names
<?php
$scores = ['ana' => 82, 'ben' => 95, 'cy' => 70, 'di' => 88];
$result = uasort($scores, fn(int $a, int $b): int => $a <=> $b);
echo json_encode($scores, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
var_dump($result);
Output
{"cy":70,"ana":82,"di":88,"ben":95}
bool(true)
Sort records by a field, descending, with stable ties
<?php
$players = [
    'p1' => ['name' => 'Ava', 'points' => 30],
    'p2' => ['name' => 'Ben', 'points' => 45],
    'p3' => ['name' => 'Cara', 'points' => 30],
    'p4' => ['name' => 'Dev', 'points' => 50],
];
uasort($players, fn(array $a, array $b): int => $b['points'] <=> $a['points']);
echo json_encode(array_keys($players)), "\n";
Output
["p4","p2","p1","p3"]
Float difference versus spaceship comparison
<?php
$prices = ['a' => 1.5, 'b' => 1.2, 'c' => 1.9];
$wrong = $prices;
uasort($wrong, fn(float $x, float $y) => $x - $y);
$right = $prices;
uasort($right, fn(float $x, float $y): int => $x <=> $y);
echo json_encode($wrong), "\n";
echo json_encode($right), "\n";
Output
{"a":1.5,"b":1.2,"c":1.9}
{"b":1.2,"a":1.5,"c":1.9}