Skip to Content
Course content

54: Array Sorting Functions in Depth

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I remember a junior dev on my team a few years back who spent an entire afternoon chasing a bug that felt like a ghost in the machine. He had an array where the keys were Product IDs and the values were their prices. He needed to display the cheapest products first, so he called sort($products). On the surface, the list looked perfect—the prices were in ascending order. But when a user clicked "Add to Cart," the wrong item was added every single time. Why? Because sort() doesn't just rearrange the values; it completely wipes out your existing keys and replaces them with new numeric indexes starting from zero. He had effectively disconnected every price from its product ID.

Preserving Relationships with Associative Sorting

This is the most common trap in PHP sorting. When you're dealing with simple lists, sort() and rsort() (for reverse) are fine. But the moment your keys actually mean something—like an ID or a username—you have to switch to the "a" variants: asort() and arsort(). The "a" stands for associative. These functions move the value and the key together as a pair, ensuring that Product ID 402 stays attached to its $19.99 price tag regardless of where it ends up in the list.

Sometimes, though, you don't care about the value; you care about the key. If you're building a directory and want the keys (the names) sorted alphabetically, ksort() is your tool. I've found that ksort() is incredibly handy when you're preparing data for a template where the order of the keys determines the order of the HTML output.

$user_scores = [
    "Zelda" => 450,
    "Alice" => 800,
    "Bob" => 600
];

// Sort by score (value), keeping the names (keys)
asort($user_scores); 
// Result: ["Zelda" => 450, "Bob" => 600, "Alice" => 800]

// Sort by name (key)
ksort($user_scores); 
// Result: ["Alice" => 800, "Bob" => 600, "Zelda" => 450]

The Power of Custom Comparison Logic

Standard sorting works great for strings and numbers, but real-world data is rarely that clean. What if you have an array of arrays—like a list of users, where each user is an array containing an 'age' and a 'name'? asort() won't know which internal key to look at. This is where usort() (user-defined sort) comes in. It allows you to write a custom function that tells PHP exactly how to compare two elements.

In older versions of PHP, this was a bit clunky, but now we have the spaceship operator (<=>). It's a lifesaver. It returns -1, 0, or 1 based on whether the left side is less than, equal to, or greater than the right side—exactly what the sorting functions expect.

$users = [
    ['name' => 'Charlie', 'age' => 30],
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 25],
];

// Sort by age ascending, then by name ascending if ages are equal
usort($users, function($a, $b) {
    return ($a['age'] <=> $b['age']) ?: ($a['name'] <=> $b['name']);
});

I love that little shorthand using the Elvis operator ?:. It basically says: "Sort by age; if the result is 0 (a tie), move on to sorting by name." If you need to keep your original keys while using a custom function, just use uasort() instead of usort(). It’s the same logic, just with key preservation.




📋 Practical Task

Build a Multi-Criteria Gaming Leaderboard

You have been given a raw array of player data. Your task is to sort this leaderboard using usort() based on the following professional gaming rules:

  • Players should be sorted primarily by score in descending order (highest score first).
  • If two players have the same score, the tie-breaker is kills in descending order.
  • If both score and kills are identical, sort them alphabetically by username in ascending order.

Starter Data:

$players = [
    ['username' => 'ShadowReaper', 'score' => 1200, 'kills' => 45],
    ['username' => 'LightBringer', 'score' => 1500, 'kills' => 60],
    ['username' => 'DarkKnight', 'score' => 1200, 'kills' => 50],
    ['username' => 'AlphaWolf', 'score' => 1500, 'kills' => 60],
    ['username' => 'Zenith', 'score' => 1100, 'kills' => 30],
];

Write the sorting logic and var_dump the resulting array to verify that 'AlphaWolf' appears before 'LightBringer' (due to alphabetical tie-break) and 'DarkKnight' appears before 'ShadowReaper' (due to the kill count tie-break).

Rating
0 0

There are no comments for now.

to be the first to leave a comment.