ZetCode

PHP Array Sorting

last modified October 22, 2026

PHP provides a family of functions for sorting arrays and objects, such as sort, asort, ksort, and usort. This tutorial covers them with practical examples.

All PHP sorting functions sort the array in place: they take the array by reference and return true, not a sorted copy. Since PHP 8.0, sorting is stable, which means that elements that compare as equal keep their original order.

FunctionSorts byKeeps keysOrder
sort / rsortvaluenoascending / descending
asort / arsortvalueyesascending / descending
ksort / krsortkeyyesascending / descending
usortvaluenouser-defined
uasortvalueyesuser-defined
uksortkeyyesuser-defined
natsort / natcasesortvalueyesnatural order

Basic sorting with sort

The sort function sorts an array in ascending order and reindexes it.

basic_sort.php
<?php

declare(strict_types=1);

$numbers = [3, 1, 4, 1, 5];
sort($numbers);
print_r($numbers);

The array [3, 1, 4, 1, 5] becomes [1, 1, 3, 4, 5]. The keys are reset to 0 through 4.

$ php basic_sort.php
Array
(
    [0] => 1
    [1] => 1
    [2] => 3
    [3] => 4
    [4] => 5
)

Sorting strings

Strings are sorted by their byte values, so uppercase letters come before lowercase ones.

sort_strings.php
<?php

declare(strict_types=1);

$fruits = ["banana", "apple", "Cherry", "date"];
sort($fruits);
echo implode(' ', $fruits), "\n";

sort($fruits, SORT_FLAG_CASE | SORT_STRING);
echo implode(' ', $fruits), "\n";

By default, "Cherry" comes first because C has a lower code than any lowercase letter. The SORT_FLAG_CASE flag, combined with SORT_STRING, makes the comparison case-insensitive.

$ php sort_strings.php
Cherry apple banana date
apple banana Cherry date

Natural order

Natural ordering sorts numbers inside strings the way people expect.

natural.php
<?php

declare(strict_types=1);

$files = ["img12.png", "img10.png", "img2.png", "img1.png"];

$copy = $files;
sort($copy);
echo implode(' ', $copy), "\n";

$copy = $files;
sort($copy, SORT_NATURAL);
echo implode(' ', $copy), "\n";

$files[] = "IMG3.png";

sort($files, SORT_NATURAL);
echo implode(' ', $files), "\n";

sort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo implode(' ', $files), "\n";

A plain sort puts img10.png before img2.png, because it compares character by character. The SORT_NATURAL flag compares the numeric parts as numbers. Adding SORT_FLAG_CASE also ignores case. The natsort and natcasesort functions do the same but keep the keys.

$ php natural.php
img1.png img10.png img12.png img2.png
img1.png img2.png img10.png img12.png
IMG3.png img1.png img2.png img10.png img12.png
img1.png img2.png IMG3.png img10.png img12.png

Preserving keys with asort and arsort

The asort function sorts by value while keeping the key associations; arsort does the same in descending order.

asort_example.php
<?php

declare(strict_types=1);

$scores = ["John" => 85, "Jane" => 92, "Bob" => 78];

asort($scores);
print_r($scores);

arsort($scores);
print_r($scores);

The names stay attached to their scores. With sort, the names would be lost and replaced by numeric keys.

$ php asort_example.php
Array
(
    [Bob] => 78
    [John] => 85
    [Jane] => 92
)
Array
(
    [Jane] => 92
    [John] => 85
    [Bob] => 78
)

Sorting by keys with ksort and krsort

The ksort function sorts an array by key in ascending order, krsort in descending order.

ksort_example.php
<?php

declare(strict_types=1);

$data = ["z" => 1, "x" => 2, "y" => 3];

ksort($data);
print_r($data);

krsort($data);
print_r($data);

The values stay tied to their original keys.

$ php ksort_example.php
Array
(
    [x] => 2
    [y] => 3
    [z] => 1
)
Array
(
    [z] => 1
    [y] => 3
    [x] => 2
)

Descending order with rsort

The rsort function sorts an array in descending order.

rsort_example.php
<?php

declare(strict_types=1);

$numbers = [3, 1, 4, 1, 5];
rsort($numbers);
echo implode(' ', $numbers), "\n";

The array is sorted from the largest to the smallest value and reindexed.

$ php rsort_example.php
5 4 3 1 1

Custom sorting with usort

The usort function sorts using a comparison callback.

usort_example.php
<?php

declare(strict_types=1);

$numbers = [10, 5, 8, 3];
usort($numbers, fn(int $a, int $b): int => $b <=> $a);
echo implode(' ', $numbers), "\n";

$words = ["sky", "blue", "a", "cloud", "be"];
usort($words, fn(string $a, string $b): int => strlen($a) <=> strlen($b));
echo implode(' ', $words), "\n";

The callback receives two elements and returns a negative number, zero, or a positive number if the first element should come before, at the same position as, or after the second. The spaceship operator <=> returns exactly these values. Swapping the operands, $b <=> $a, reverses the order. The second call sorts words by length.

$ php usort_example.php
10 8 5 3
a be sky blue cloud

Sorting objects by property

Use usort to sort objects by a property value.

sort_objects.php
<?php

declare(strict_types=1);

final class Product
{
    public function __construct(
        public string $name,
        public float $price,
    ) {}
}

$products = [
    new Product("Phone", 500),
    new Product("Laptop", 1000),
    new Product("Tablet", 300),
];

usort($products, fn(Product $a, Product $b): int => $a->price <=> $b->price);

foreach ($products as $product) {
    printf("%-8s %7.2f\n", $product->name, $product->price);
}

The products are ordered by price, from the cheapest to the most expensive.

$ php sort_objects.php
Tablet    300.00
Phone     500.00
Laptop   1000.00

Sorting associative arrays with uasort

The uasort function sorts by value with a callback and preserves the keys.

uasort_example.php
<?php

declare(strict_types=1);

$scores = ["John" => 85, "Jane" => 92, "Bob" => 78];

uasort($scores, fn(int $a, int $b): int => $b <=> $a);
print_r($scores);

The scores are sorted in descending order, with the names intact.

$ php uasort_example.php
Array
(
    [Jane] => 92
    [John] => 85
    [Bob] => 78
)

Sorting by key with uksort

The uksort function sorts by key using a callback.

uksort_example.php
<?php

declare(strict_types=1);

$data = ["kiwi" => 1, "fig" => 2, "banana" => 3, "plum" => 4];

uksort($data, fn(string $a, string $b): int => strlen($a) <=> strlen($b));
print_r($data);

The keys are sorted by length. The keys "kiwi" and "plum" have the same length, so they keep their original order; this is the stable sorting guaranteed since PHP 8.0.

$ php uksort_example.php
Array
(
    [fig] => 2
    [kiwi] => 1
    [plum] => 4
    [banana] => 3
)

Stable sorting

Stability matters when sorting data that is already ordered by another criterion.

stable.php
<?php

declare(strict_types=1);

$tasks = [
    ["Write report", 2],
    ["Call client", 1],
    ["Fix bug", 1],
    ["Review code", 2],
    ["Reply to email", 1],
];

usort($tasks, fn(array $a, array $b): int => $a[1] <=> $b[1]);

foreach ($tasks as [$task, $priority]) {
    echo "$priority $task\n";
}

The tasks are sorted by priority. Tasks with the same priority stay in the order in which they were added. Before PHP 8.0, their order was not guaranteed.

$ php stable.php
1 Call client
1 Fix bug
1 Reply to email
2 Write report
2 Review code

Sorting multidimensional arrays

Arrays of rows can be sorted by a specific key with usort.

sort_multi.php
<?php

declare(strict_types=1);

$users = [
    ["name" => "John", "age" => 25],
    ["name" => "Jane", "age" => 30],
    ["name" => "Bob", "age" => 20],
];

usort($users, fn(array $a, array $b): int => $a["age"] <=> $b["age"]);

foreach ($users as $user) {
    echo "{$user['name']} ({$user['age']})\n";
}

The users are sorted by age, from the youngest to the oldest.

$ php sort_multi.php
Bob (20)
John (25)
Jane (30)

Sorting by multiple criteria

Arrays are compared element by element with the spaceship operator, which makes multi-criteria sorting concise.

sort_multi_criteria.php
<?php

declare(strict_types=1);

final class Item
{
    public function __construct(
        public string $name,
        public int $stock,
    ) {}
}

$items = [
    new Item("Tablet", 5),
    new Item("Phone", 10),
    new Item("Laptop", 5),
    new Item("Charger", 10),
];

usort($items, fn(Item $a, Item $b): int =>
    [$b->stock, $a->name] <=> [$a->stock, $b->name]);

foreach ($items as $item) {
    echo "$item->name ($item->stock)\n";
}

The items are sorted by stock in descending order and then by name in ascending order. Putting $b->stock on the left side reverses the first criterion. If the stock values are equal, the names decide.

$ php sort_multi_criteria.php
Charger (10)
Phone (10)
Laptop (5)
Tablet (5)

Sorting with array_multisort

The array_multisort function sorts several arrays at once. Combined with array_column, it sorts rows by several columns.

array_multisort_example.php
<?php

declare(strict_types=1);

$users = [
    ["name" => "John", "age" => 25],
    ["name" => "Jane", "age" => 30],
    ["name" => "Bob", "age" => 25],
    ["name" => "Anna", "age" => 30],
];

$ages = array_column($users, 'age');
$names = array_column($users, 'name');

array_multisort($ages, SORT_DESC, $names, SORT_ASC, $users);

foreach ($users as $user) {
    echo "{$user['name']} ({$user['age']})\n";
}

The ages are sorted in descending order, ties are broken by name in ascending order, and the $users array, passed last, is rearranged in the same way.

$ php array_multisort_example.php
Anna (30)
Jane (30)
Bob (25)
John (25)

Sorting users by age

This example sorts user objects by date of birth.

sort_users_by_age.php
<?php

declare(strict_types=1);

final class User
{
    public DateTimeImmutable $dateOfBirth;

    public function __construct(
        public string $firstName,
        public string $lastName,
        string $dateOfBirth,
    ) {
        $this->dateOfBirth = new DateTimeImmutable($dateOfBirth);
    }
}

$users = [
    new User("John", "Doe", "2000-05-15"),
    new User("Jane", "Smith", "1995-08-22"),
    new User("Bob", "Brown", "1998-11-30"),
];

usort($users, fn(User $a, User $b): int => $a->dateOfBirth <=> $b->dateOfBirth);

$today = new DateTimeImmutable('2026-10-22');

foreach ($users as $user) {
    $age = $user->dateOfBirth->diff($today)->y;
    echo "$user->firstName $user->lastName, {$user->dateOfBirth->format('Y-m-d')}, $age years\n";
}

The date of birth is stored as a DateTimeImmutable, which can be compared directly with the spaceship operator. The oldest user comes first. The age is computed with diff against a fixed date to keep the output stable.

$ php sort_users_by_age.php
Jane Smith, 1995-08-22, 31 years
Bob Brown, 1998-11-30, 27 years
John Doe, 2000-05-15, 26 years

Getting a sorted copy

Because the sorting functions work in place, a small helper is useful when the original order must be kept.

sorted_copy.php
<?php

declare(strict_types=1);

function sorted(array $values, ?callable $cmp = null): array
{
    $cmp === null ? sort($values) : usort($values, $cmp);

    return $values;
}

$numbers = [3, 1, 2];

$asc = sorted($numbers);
$desc = sorted($numbers, fn(int $a, int $b): int => $b <=> $a);

echo implode(' ', $numbers), "\n";
echo implode(' ', $asc), "\n";
echo implode(' ', $desc), "\n";

Arrays are passed to functions by value, so the helper sorts its own copy and returns it. The original $numbers array is unchanged.

$ php sorted_copy.php
3 1 2
1 2 3
3 2 1

Best practices for sorting

Source

PHP Sorting Arrays - Documentation

In this article, we have explored sorting arrays and objects in PHP, including custom comparisons, natural order, stable sorting, and multi-criteria sorting.

Author

My name is Jan Bodnar, a passionate programmer with over a decade of experience. I've written 1400+ articles and 8 e-books since 2007.

List all PHP tutorials.