Operator perbandingan biasa menjawab satu pertanyaan saja: < menjawab “lebih kecil?”, == menjawab “sama?”. Namun banyak algoritma — terutama pengurutan — butuh ketiganya sekaligus: lebih kecil, sama, atau lebih besar. Sebelum PHP 7, kita menulis tiga perbandingan berturut-turut; kini cukup satu operator: spaceship (<=>), yang mengembalikan -1, 0, atau 1 sesuai posisi kedua nilai. Pada Chapter ini kita akan mempelajari semantik spaceship pada angka, string, dan array, lalu memakainya untuk mengurutkan data dengan fungsi usort().

Perbandingan Tiga Arah #

Spaceship operator mengevaluasi $a <=> $b dengan hasil pasti salah satu dari tiga nilai integer:

php
<?php
var_dump(5 <=> 3);
var_dump(3 <=> 5);
var_dump(5 <=> 5);

var_dump(1.5 <=> 1.7);
var_dump(true <=> false);

Output yang Dihasilkan:

text
int(1)
int(-1)
int(0)
int(-1)
int(1)

Aturannya ringkas: -1 bila operand kiri lebih kecil, 1 bila lebih besar, dan 0 bila keduanya setara. Ketiga hasil ini sengaja dipilih agar cocok dengan konvensi three-way comparison yang sudah lama dipakai fungsi pembanding di banyak bahasa pemrograman — nanti kita lihat bahwa usort() memang berharap tepat nilai-nilai ini. Perhatikan bahwa spaceship juga membandingkan float dan boolean dengan aturan perbandingan PHP yang sama seperti operator < dan >.

Membandingkan String #

Untuk string, spaceship mengikuti aturan perbandingan standar PHP: jika kedua string adalah string numerik (seperti "10" dan "9"), keduanya dibandingkan sebagai angka; jika tidak, perbandingan dilakukan per karakter dari kiri:

php
<?php
var_dump("apel" <=> "jeruk");
var_dump("a" <=> "A");

var_dump("10" <=> "9");
var_dump("2" <=> "10");
var_dump(10 <=> 9);

Output yang Dihasilkan:

text
int(-1)
int(1)
int(1)
int(-1)
int(1)

Perhatikan ketiga baris terakhir dengan saksama — inilah sumber kejutan klasik. "10" <=> "9" menghasilkan 1 karena keduanya string numerik sehingga dibandingkan sebagai angka (10 > 9), hasil yang sama dengan 10 <=> 9. Sementara "apel" <=> "jeruk" dan "a" <=> "A" membandingkan kode karakter: huruf pertama a (kode 97) lebih kecil dari j, dan lebih besar dari A besar (kode 65) — itulah mengapa hasilnya -1 lalu 1. Campuran "2" <=> "10" kembali numerik (2 < 10).

Membandingkan Array #

Array dibandingkan element demi element dari kiri; bila semua element awal setara, array yang lebih pendek dianggap lebih kecil:

php
<?php
var_dump([1, 2, 3] <=> [1, 2, 3]);
var_dump([1, 2, 4] <=> [1, 2, 3]);
var_dump([1, 2] <=> [1, 2, 0]);

Output yang Dihasilkan:

text
int(0)
int(1)
int(-1)

Baris pertama menghasilkan 0 karena semua element setara. Baris kedua menemukan perbedaan di element ketiga (4 vs 3) sehingga menghasilkan 1. Baris ketiga memperlihatkan aturan panjang: element yang ada semuanya setara, maka array dengan dua element kalah dari array dengan tiga element. Aturan ini identik dengan perilaku operator < dan > pada array — spaceship hanya membungkusnya menjadi satu hasil.

Dari Tiga Operator Menjadi Satu #

Nilai usort()-friendly inilah alasan utama spaceship lahir. Sebelum PHP 7, fungsi pembanding harus menulis tiga cabang secara manual:

php
<?php
function bandingkanCaraLama(int $a, int $b): int {
    if ($a < $b) {
        return -1;
    }
    if ($a > $b) {
        return 1;
    }
    return 0;
}

function bandingkanCaraBaru(int $a, int $b): int {
    return $a <=> $b;
}

echo bandingkanCaraLama(3, 7) . bandingkanCaraLama(7, 3) . bandingkanCaraLama(7, 7) . "\n";
echo bandingkanCaraBaru(3, 7) . bandingkanCaraBaru(7, 3) . bandingkanCaraBaru(7, 7) . "\n";

Output yang Dihasilkan:

text
-110
-110

Kedua baris keluaran identik: string -110 adalah perangkaian tiga hasil terpisah (-1, lalu 1, lalu 0). Perbedaannya ada pada jumlah kode: versi baru hanya membutuhkan satu baris logika. (Fungsi sendiri baru dibahas tuntas pada Section Fungsi; di sini cukup pahami bahwa bandingkanCaraLama dan bandingkanCaraBaru menerima dua angka dan mengembalikan -1, 0, atau 1.)

Praktik dengan usort #

Fungsi bawaan usort(array &$array, callable $callback) mengurutkan array dengan memanggil $callback berulang kali untuk membandingkan dua element; usort() membaca nilai kembaliannya persis seperti hasil spaceship. Contoh berikut mengurutkan daftar produk dari harga termurah:

php
<?php
$produk = [
    ["nama" => "Monitor", "harga" => 1500000],
    ["nama" => "Keyboard", "harga" => 350000],
    ["nama" => "Laptop", "harga" => 8500000],
];

usort($produk, function ($a, $b) {
    return $a["harga"] <=> $b["harga"];
});

foreach ($produk as $item) {
    echo $item["nama"] . ": Rp" . $item["harga"] . "\n";
}

Output yang Dihasilkan:

text
Keyboard: Rp350000
Monitor: Rp1500000
Laptop: Rp8500000

Mari kita bedah cara kerjanya:

  1. Argumen pertama ($produk): array yang ingin diurutkan, dikirim sebagai referensi sehingga perubahan langsung berlaku pada variabel aslinya.
  2. Argumen kedua (function ($a, $b) { ... }): callback — fungsi tanpa nama yang dipanggil usort() setiap kali butuh membandingkan dua element.
  3. Isi callback ($a["harga"] <=> $b["harga"]): hasil -1 memberi tahu usort() bahwa $a harus berdiri sebelum $b; 1 sebaliknya; 0 berarti urutannya bebas.

Mengurutkan dari harga termahal kini hanya soal menukar posisi operand: return $b["harga"] <=> $a["harga"]; — kebalikan arah perbandingan membalik arah urutan. (Struktur foreach untuk mencetak hasilnya dibahas tuntas pada Section Control Flow; usort() sendiri dibahas lebih jauh pada Section Arrays dan Collections.)

Berkas contoh.php pada bagian bawah halaman mendemonstrasikan pengurutan naik dan turun sekaligus dalam satu program utuh.

Ringkasan #

Spaceship operator $a <=> $b menghasilkan -1, 0, atau 1 dalam satu ekspresi — ringkasan dari <, ==, dan > sekaligus. Perbandingannya mengikuti aturan standar PHP: string numerik dibandingkan sebagai angka, array dibandingkan element demi element, dan hasilnya selalu salah satu dari tiga integer itu. Kombinasi <=> dengan usort() mengubah tiga cabang if menjadi satu baris. Selanjutnya kita pelajari operator yang mengubah nilai dengan efek samping pada variabelnya sendiri: increment dan decrement.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh.php

Unduh berkas
php
<?php
// contoh.php — rangkuman Spaceship Operator
// Jalankan dengan: php contoh.php

// 1. Perbandingan tiga arah pada angka
echo "5 <=> 3   : ", var_export(5 <=> 3, true), "\n";
echo "3 <=> 5   : ", var_export(3 <=> 5, true), "\n";
echo "5 <=> 5   : ", var_export(5 <=> 5, true), "\n";

// 2. String numerik dibandingkan sebagai angka, string biasa per karakter
echo "\"10\" <=> \"9\" : ", var_export("10" <=> "9", true), "\n";
echo "\"apel\" <=> \"jeruk\" : ", var_export("apel" <=> "jeruk", true), "\n";

// 3. Array: element demi element, lalu panjang
echo "[1,2] <=> [1,2,0] : ", var_export([1, 2] <=> [1, 2, 0], true), "\n";

// 4. Pengurutan naik dan turun dengan usort + spaceship
$produk = [
    ["nama" => "Monitor", "harga" => 1500000],
    ["nama" => "Keyboard", "harga" => 350000],
    ["nama" => "Laptop", "harga" => 8500000],
];

usort($produk, function ($a, $b) {
    return $a["harga"] <=> $b["harga"];
});

echo "Termurah dulu:\n";
foreach ($produk as $item) {
    echo "  {$item['nama']}: Rp{$item['harga']}\n";
}

usort($produk, function ($a, $b) {
    return $b["harga"] <=> $a["harga"];
});

echo "Termahal dulu:\n";
foreach ($produk as $item) {
    echo "  {$item['nama']}: Rp{$item['harga']}\n";
}