Table Of Contents
Problem
You need to compare two values and determine if the first is less than, equal to, or greater than the second, requiring verbose if-else statements.
Solution
// Traditional comparison
function compare($a, $b) {
if ($a < $b) {
return -1;
} elseif ($a > $b) {
return 1;
} else {
return 0;
}
}
// With spaceship operator
function compare($a, $b) {
return $a <=> $b;
}
// Returns:
// -1 if $a < $b
// 0 if $a == $b
// 1 if $a > $b
echo 1 <=> 2; // -1
echo 2 <=> 2; // 0
echo 3 <=> 2; // 1
// Sorting arrays with spaceship operator
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];
// Sort ascending
usort($numbers, fn($a, $b) => $a <=> $b);
// Result: [1, 1, 2, 3, 4, 5, 6, 9]
// Sort descending
usort($numbers, fn($a, $b) => $b <=> $a);
// Result: [9, 6, 5, 4, 3, 2, 1, 1]
// Sorting objects by property
class Product {
public $name;
public $price;
public function __construct($name, $price) {
$this->name = $name;
$this->price = $price;
}
}
$products = [
new Product('Laptop', 999),
new Product('Phone', 599),
new Product('Tablet', 299)
];
// Sort by price
usort($products, fn($a, $b) => $a->price <=> $b->price);
// Sort by name
usort($products, fn($a, $b) => $a->name <=> $b->name);
// Multi-level sorting
usort($products, function($a, $b) {
// First by price, then by name
return $a->price <=> $b->price ?: $a->name <=> $b->name;
});
// String comparison
$strings = ['apple', 'Banana', 'cherry'];
// Case-sensitive comparison
usort($strings, fn($a, $b) => $a <=> $b);
// Result: ['Banana', 'apple', 'cherry']
// Case-insensitive comparison
usort($strings, fn($a, $b) => strtolower($a) <=> strtolower($b));
// Result: ['apple', 'Banana', 'cherry']
// Date comparison
$dates = [
new DateTime('2023-12-01'),
new DateTime('2023-01-15'),
new DateTime('2023-06-30')
];
usort($dates, fn($a, $b) => $a <=> $b);
// Array comparison (element by element)
$array1 = [1, 2, 3];
$array2 = [1, 2, 4];
$array3 = [1, 2, 3];
echo $array1 <=> $array2; // -1
echo $array1 <=> $array3; // 0
// Version comparison
function compareVersions($v1, $v2) {
$version1 = explode('.', $v1);
$version2 = explode('.', $v2);
for ($i = 0; $i < max(count($version1), count($version2)); $i++) {
$part1 = (int)($version1[$i] ?? 0);
$part2 = (int)($version2[$i] ?? 0);
$result = $part1 <=> $part2;
if ($result !== 0) {
return $result;
}
}
return 0;
}
echo compareVersions('1.2.3', '1.2.4'); // -1
echo compareVersions('2.0.0', '1.9.9'); // 1
// Custom comparison for complex sorting
class User {
public $name;
public $age;
public $lastLogin;
public function __construct($name, $age, $lastLogin) {
$this->name = $name;
$this->age = $age;
$this->lastLogin = new DateTime($lastLogin);
}
}
$users = [
new User('Alice', 30, '2023-12-01'),
new User('Bob', 25, '2023-12-02'),
new User('Charlie', 30, '2023-11-30')
];
// Sort by age, then by last login (newest first)
usort($users, function($a, $b) {
return $a->age <=> $b->age ?: $b->lastLogin <=> $a->lastLogin;
});
// Using in conditional logic
function processOrder($priority) {
$urgency = $priority <=> 5;
switch ($urgency) {
case -1:
return 'Low priority order';
case 0:
return 'Normal priority order';
case 1:
return 'High priority order';
}
}
echo processOrder(3); // Low priority order
echo processOrder(5); // Normal priority order
echo processOrder(8); // High priority order
Explanation
The spaceship operator <=>
performs a three-way comparison, returning -1, 0, or 1. It's perfect for sorting callbacks and comparison functions.
Use it with usort()
, uasort()
, and uksort()
for clean, readable sorting logic. It works with numbers, strings, arrays, and objects that implement comparison.
Share this article
Add Comment
No comments yet. Be the first to comment!