Combined Comparison Operator
Some built-in PHP functions require passing of a callable (a
function), for example sorting methods like usort()
that require comparison methods or functions. A classic example
would be trying to sort a collection or an array of objects. Since
we cannot compare the objects directly, we have to call a comparison
method. If, at some point in the future, PHP will support operator
overloading, this might not be necessary anymore. But as of today,
we have to write a comparison function, usually as an anonymous
function, that compares two objects:
class Appointment
{
private DateTimeImmutable $date;
public function __construct(DateTimeImmutable $date)
{
$this->date = $date;
}
public function getDate(): DateTimeImmutable
{
return $this->date;
}
}
$collection = [
new Appointment(new DateTimeImmutable('2016-07-02')),
new Appointment(new DateTimeImmutable('2016-06-06')),
new Appointment(new DateTimeImmutable('2016-05-04'))
];
var_dump($collection);
usort(
$collection,
function($a, $b) {
$dateA = $a->getDate();
$dateB = $b->getDate();
if ($dateA > $dateB) {
return 1;
}
if ($dateA < $dateB) {
return -1;
}
if ($dateA == $dateB) {
return 0;
}
}
);
var_dump($collection);
In this example, we want to sort our Appointment
object instances by date value. They are no scalar values, so we
cannot just compare two instances using comparison operators
==
or <
, but we have to retrieve the
dates first by calling the getDate()
method, and can
then compare the values.
The second argument to usort()
is a comparison
function that either returns -1
, 1
or
0
based on the result of the comparison. While this
works fine, it is quite a bit of code to achieve such a simple
task.
Luckily, PHP 7 features the new combined comparison
operator <=>
that makes is a lot easier to
write comparison functions:
usort(
$collection,
function($a, $b)
{
return $a->getDate() <=> $b->getDate();
}
);
The combined comparison operator, colloquially also called the
spaceship operator, because it somewhat looks like a TIE fighter in
Star Wars, will compare the two given values and either return
-1
, 1
or 0
based on the
result.
Now we can run our sorting code with the shortened call to
usort()
:
array(3) {
[0] =>
class Appointment#1 (1) {
private $date =>
class DateTimeImmutable#2 (3) {
public $date =>
string(26) "2016-07-02 00:00:00.000000"
// ...
}
}
[1] =>
class Appointment#3 (1) {
private $date =>
class DateTimeImmutable#4 (3) {
public $date =>
string(26) "2016-06-06 00:00:00.000000"
// ...
}
}
[2] =>
class Appointment#5 (1) {
private $date =>
class DateTimeImmutable#6 (3) {
public $date =>
string(26) "2016-05-04 00:00:00.000000"
// ...
}
}
}
array(3) {
[0] =>
class Appointment#5 (1) {
private $date =>
class DateTimeImmutable#6 (3) {
public $date =>
string(26) "2016-05-04 00:00:00.000000"
// ...
}
}
[1] =>
class Appointment#3 (1) {
private $date =>
class DateTimeImmutable#4 (3) {
public $date =>
string(26) "2016-06-06 00:00:00.000000"
// ...
}
}
[2] =>
class Appointment#1 (1) {
private $date =>
class DateTimeImmutable#2 (3) {
public $date =>
string(26) "2016-07-02 00:00:00.000000"
// ...
}
}
}
As we can see, the objects that initially were unsorted have been sorted by date in ascending order.