Signature
uksort(array &$array, callable $callback): truePurpose
uksort() sorts an array by its keys using a comparison function that you write. Each key keeps its value, so the pairs move together. Use it when the built-in key sorters such as ksort() cannot express your rule. Examples are ordering by key length, ignoring a leading article, or following a custom ranking.
The array is sorted in place. The function does not return a new array.
Signature
Parameters
$array: the array to sort. It is passed by reference, so you must pass a variable, not a literal or a function result. There is no default.$callback: a callable that receives two keys,$aand$b. It must return an integer that is less than zero, zero, or greater than zero, meaning that$acomes before, ties with, or comes after$b. There is no default.
The spaceship operator <=>, strcmp() and strcasecmp() all return values suited to this job.
Return value and failures
Since PHP 8.2 the declared return type is true, and the function always returns true. Earlier versions declared bool, but the practical result was the same. The real effect is the reordering of the variable you passed.
Two behaviors from the manual are worth remembering:
- If two keys compare as equal, they keep their original relative order. Before PHP 8.0.0 that order was undefined.
- The array's internal pointer is reset to the first element.
A TypeError is raised if the first argument is not an array or the callback is not callable. If the callback throws, the exception propagates to your code.
Example 1: sort by key length
The callback compares only a property of the keys. Keys of equal length stay in their original order, because equal members are not reshuffled.
$data = ["pear" => 3, "fig" => 1, "banana" => 2, "kiwi" => 5];
uksort($data, fn(int|string $a, int|string $b): int => strlen($a) <=> strlen($b));
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"fig":1,"pear":3,"kiwi":5,"banana":2}
pear and kiwi both have four characters, so pear stays ahead of kiwi.
Example 2: ignore a leading article
This follows the idea in the official manual. A helper normalizes each key before the case-insensitive comparison, so "an apple" sorts under A and "the Earth" under E.
function strip_article(string $key): string
{
return preg_replace('/^(a|an|the) /i', '', $key);
}
$data = ["John" => 1, "the Earth" => 2, "an apple" => 3, "a banana" => 4];
uksort($data, fn(string $a, string $b): int => strcasecmp(strip_article($a), strip_article($b)));
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"an apple":3,"a banana":4,"the Earth":2,"John":1}
Example 3: descending integer keys and the return value
Here the callback reverses the usual order by swapping the operands. The example also prints the return value.
$data = [10 => "ten", 2 => "two", 33 => "thirty-three"];
$result = uksort($data, fn(int|string $a, int|string $b): int => $b <=> $a);
echo json_encode($result), "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";true
{"33":"thirty-three","10":"ten","2":"two"}
The result is true, and the array now runs from the largest key to the smallest.
Edge cases
- Numeric string keys become integers. A key such as
"10"is stored as the integer10, so your callback receives an integer. Avoid strict string-only assumptions, or use a union type likeint|string. - Empty and single-element arrays are left unchanged, and the callback may never run.
- Keys are preserved. Unlike
usort(),uksort()does not renumber anything. - Mixed key types need a callback that handles both integers and strings consistently. An inconsistent comparison, where A < B and B < A can both hold, gives unreliable ordering.
- By-reference callback parameters. The manual notes that, since PHP 8.0.0, a callback that expects a parameter by reference causes an
E_WARNING.
Common mistakes
- Comparing values instead of keys. The callback only sees keys. To order by value, use
uasort()orusort(). - Expecting a sorted copy. The return value is just
true. Writing$sorted = uksort($a, ...)does not give you an array. - Returning a float. Return values are cast to
int, so0.5and0.99become0and compare as equal. Subtracting fractional numbers is therefore risky. Use<=>instead. - Returning a boolean. A callback like
$a > $bonly yieldstrueorfalse, never a negative result, so it does not describe the ordering fully. Prefer<=>. - Forgetting case rules.
strcmp()is case-sensitive, so uppercase letters sort before lowercase ones. Usestrcasecmp()when case should not matter. - Passing a non-variable. Because the array is taken by reference,
uksort(getData(), ...)is not valid.
Related functions
usort(): sort by values with a user-defined comparison, then renumber keys.uasort(): sort by values with a user-defined comparison, keeping key association.ksort(): sort by keys using standard comparison flags, with no callback.strcmp(),strcasecmp(),strnatcmp(): ready-made string comparisons for callbacks.
Recap
uksort() reorders an array in place by keys, using a callback that returns a negative, zero or positive integer. It keeps key-value pairs together, preserves the original order of ties, resets the internal pointer and always returns true. Use <=> for reliable results, remember that numeric string keys arrive as integers, and reach for uasort() when the ordering depends on values.
Tested examples
$data = ["pear" => 3, "fig" => 1, "banana" => 2, "kiwi" => 5];
uksort($data, fn(int|string $a, int|string $b): int => strlen($a) <=> strlen($b));
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"fig":1,"pear":3,"kiwi":5,"banana":2}
function strip_article(string $key): string
{
return preg_replace('/^(a|an|the) /i', '', $key);
}
$data = ["John" => 1, "the Earth" => 2, "an apple" => 3, "a banana" => 4];
uksort($data, fn(string $a, string $b): int => strcasecmp(strip_article($a), strip_article($b)));
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"an apple":3,"a banana":4,"the Earth":2,"John":1}
$data = [10 => "ten", 2 => "two", 33 => "thirty-three"];
$result = uksort($data, fn(int|string $a, int|string $b): int => $b <=> $a);
echo json_encode($result), "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";true
{"33":"thirty-three","10":"ten","2":"two"}