Satu baris ekspresi bisa memuat banyak operator sekaligus, dan PHP harus memutuskan mana yang dievaluasi lebih dulu. Aturan pengurutan itu bernama operator precedence: 1 + 2 * 3 menghasilkan 7 karena perkalian menang lawan penjumlahan, bukan 9 seperti bila dibaca dari kiri. Sebagian besar aturannya cocok dengan naluri matematika sekolah, tetapi beberapa kombinasi — terutama yang melibatkan penggabungan string, and/or, dan penugasan — terkenal menjebak bahkan programmer berpengalaman. Pada Chapter ini kita akan memetakan urutan precedence PHP, membuktikan jebakan-jebakannya dengan eksekusi nyata, dan membentuk kebiasaan menulis ekspresi yang tidak menyisakan ruang salah tafsir.
Urutan Evaluasi Default #
Ketika dua operator berbagi satu ekspresi tanpa tanda kurung, yang berprecedence lebih tinggi dievaluasi lebih dulu. Tanda kurung selalu bisa menimpa urutan tersebut:
<?php
$hasil = 1 + 2 * 3;
echo $hasil . "\n";
$hasilDenganKurung = (1 + 2) * 3;
echo $hasilDenganKurung . "\n";Output yang Dihasilkan:
7
9Pada baris ketiga, 2 * 3 dievaluasi lebih dulu menjadi 6, baru ditambah 1. Tanda kurung pada baris keenam memaksa 1 + 2 selesai lebih dulu menjadi 3, lalu dikalikan 3. Membaca keluaran seperti ini memang terasa sepele — jebakan sesungguhnya menunggu di kombinasi operator yang lebih jarang kita sadari urutannya.
Peta Precedence Operator PHP #
Tabel berikut merangkum level-level yang paling sering bersinggungan sehari-hari, diurutkan dari yang tertinggi (dievaluasi pertama) ke terendah. Nama lengkap setiap operator bisa Anda telusuri kembali di chapter-chapter sebelumnya pada Section ini:
| Prioritas | Operator | Asosiativitas | Contoh |
|---|---|---|---|
| 1 (tertinggi) | ** | kanan | 2 ** 3 ** 2 |
| 2 | ++ -- ~ (int) (bool) ! | kanan | !$valid, (int) $harga |
| 3 | * / % | kiri | 10 / 5 * 2 |
| 4 | + - | kiri | 1 + 2 - 3 |
| 5 | << >> | kiri | $nilai << 2 |
| 6 | . | kiri | "a" . "b" . "c" |
| 7 | < <= > >= | tanpa | $usia >= 17 |
| 8 | == != === !== <=> | tanpa | $a === $b |
| 9-11 | & lalu ^ lalu ` | ` | kiri |
| 12 | && | kiri | $a && $b |
| 13 | ` | ` | |
| 14 | ?? | kanan | $x ?? $y |
| 15 | ?: (ternary) | kanan | $x ? $a : $b |
| 16 | = += -= .= ??= dll. | kanan | $x = $y = 5 |
| 17 (terendah) | and xor or | kiri | $a and $b |
Dua catatan penting untuk tabel ini. Pertama, kolom asosiativitas mengatur operator-operator yang setara precedence: kiri berarti yang paling kiri dievaluasi dulu (10 - 4 - 2 = (10 - 4) - 2 = 4), sedangkan kanan berarti sebaliknya. Kedua, tabel php.net memuat level tambahan seperti clone, new, dan instanceof yang kita lewati di sini karena jarang bersinggungan dengan operator lain — rujukan lengkapnya ada di bagian Referensi.
Asosiativitas dan Pangkat #
Operator pangkat ** adalah contoh terbaik untuk merasakan asosiativitas kanan. Ekspresi berikut menghitung 3 ** 2 terlebih dahulu, baru hasilnya menjadi pangkat dari 2:
<?php
var_dump(2 ** 3 ** 2);
var_dump((2 ** 3) ** 2);
var_dump(-2 ** 2);Output yang Dihasilkan:
int(512)
int(64)
int(-4)Hasil pertama adalah 512 (= 2 ** 9) karena asosiativitas kanan mengelompokkan ekspresi sebagai 2 ** (3 ** 2); tanda kurung pada baris kedua memaksa pengelompokan kiri sehingga hasilnya 64. Baris ketiga memperlihatkan aturan lain yang sering mengejutkan: -2 ** 2 adalah -(2 ** 2) = -4, karena unary minus memiliki precedence lebih rendah daripada **. Penugasan juga berasosiatif kanan, sehingga $x = $y = 5 mengisi $y dahulu, lalu nilai itu disalin ke $x — dua variabel sama-sama bernilai 5.
Jebakan Konkatenasi dan Penjumlahan #
Perubahan precedence paling terkenal dalam sejarah PHP modern terjadi di PHP 8.0: operator penggabung string (.) diturunkan posisinya di bawah + dan -. Akibatnya, penjumlahan kini selalu selesai sebelum teks digabungkan:
<?php
echo "sum: " . 1 + 2 . "\n";
echo 3 * 2 . "!\n";Output yang Dihasilkan:
sum: 3
6!Pada baris pertama, ekspresi dikelompokkan menjadi "sum: " . (1 + 2) . "\n" — angka 1 dan 2 dijumlahkan dulu menjadi 3, baru digabung dengan teks di kedua sisinya. Baris kedua serupa: 3 * 2 selesai menjadi 6 lebih dulu. Pada PHP 7 urutannya kebalikan, ("sum: " . 1) + 2, yang memaksa PHP mengubah teks "sum: 1" menjadi angka dan menghasilkan 2 disertai peringatan — perilaku lama inilah yang mendorong perubahan tersebut.
Perubahan ini juga membuat satu jebakan baru: ketika operand penjumlahan “nyasar” ke sisi yang Anda kira milik string, TypeError menghentikan program:
<?php
echo "Stok: " . 3 + "apel";Kode di atas lolos pemeriksaan sintaks, tetapi saat dijalankan PHP mengelompokkannya sebagai "Stok: " . (3 + "apel") — dan 3 + "apel" adalah penjumlahan integer dengan string non-numerik yang tidak lagi diizinkan di PHP 8:
Fatal error: Uncaught TypeError: Unsupported operand types: int + string in contoh.php on line 2Pesan di atas diambil dari eksekusi nyata di PHP 8.4. Solusinya bukan sekadar menggeser tanda, melainkan memisahkan tanggung jawab: hitung dulu di variabel bernomor jelas, atau bungkus bagian aritmetika dengan tanda kurung seperti echo "Stok: " . (3 + $tambahan); agar niat kode terbaca sejak pandangan pertama.
&& Lebih Kuat dari || #
Pada ekspresi logika campuran, && selalu menang lawan || — sejalan dengan perkalian yang menang lawan penjumlahan di aritmatika:
<?php
var_dump(true || false && false);
var_dump((true || false) && false);Output yang Dihasilkan:
bool(true)
bool(false)Baris pertama dikelompokkan sebagai true || (false && false) sehingga hasilnya true. Tanda kurung pada baris kedua membalik pengelompokan dan menghasilkan false. Tanpa tanda kurung, pembaca sering menerjemahkan a || b && c sebagai “(a atau b) dan c” — dua hasil yang berbeda total dari teks yang sama persis.
Jebakan and dan or #
Dua baris terakhir tabel precedence menyimpan jebakan yang bahkan menghabiskan berjam-jam waktu banyak programmer: versi huruf kecil and, or, xor punya precedence lebih rendah daripada tanda sama dengan (=):
<?php
$hasil1 = true and false;
var_dump($hasil1);
$hasil2 = true && false;
var_dump($hasil2);Output yang Dihasilkan:
bool(true)
bool(false)Baris pertama dikelompokkan sebagai ($hasil1 = true) and false — penugasan selesai dulu, $hasil1 terisi true, lalu hasil and yang tidak dipakai siapa pun dibuang. Baris keempat dengan && dikelompokkan sebagai $hasil2 = (true && false) sehingga $hasil2 terisi false. Kedua operator ini bekerja sama logikanya (dan sama-sama short-circuit), tetapi precedence-nya berbeda derajat. Praktik industri PHP hampir selalu memilih &&/|| untuk ekspresi dan menyisakan and/or hanya untuk pola khusus seperti $berhasil = simpan() or catatError();.
Tanda Kurung untuk Kejelasan #
Setelah melihat jebakan-jebakan di atas, kesimpulan praktisnya bukan “hafalkan tabelnya”, melainkan “tulis niat Anda secara eksplisit”. Tanda kurung tidak mengubah performa apa pun — PHP hanya mengikuti pengelompokan yang sudah jelas. Bandingkan dua baris berikut, keduanya benar, tetapi yang kedua tidak menyisakan ruang salah baca:
<?php
$umur = 25;
$status1 = $umur >= 13 && $umur <= 19 ? "remaja" : "bukan remaja";
$status2 = ($umur >= 13 && $umur <= 19) ? "remaja" : "bukan remaja";
echo $status1 . "\n";
echo $status2 . "\n";Output yang Dihasilkan:
bukan remaja
bukan remajaBerkas contoh.php pada bagian bawah halaman merangkum seluruh eksperimen Chapter ini sehingga Anda bisa mengubah nilainya dan mengamati ulang setiap pengelompokan.
Ringkasan #
Operator precedence menentukan urutan evaluasi ketika banyak operator berbagi satu ekspresi: pangkat dan unary di puncak, lalu aritmetika, perbandingan, logika, hingga penugasan — dengan and/or di dasar tabel. PHP 8 menurunkan posisi . di bawah +/-, mengubah hasil "sum: " . 1 + 2 menjadi "sum: 3" dan memindahkan jebakan lama ke TypeError pada penjumlahan string non-numerik. Tanda kurung gratis, jadi gunakanlah — ekspresi yang jelas selalu menang lawan yang ringkas tapi menuntut hafalan. Dengan peta precedence lengkap, kita siap membahas topik penutup Section ini: truthiness dan short-circuit.
Referensi #
- Tabel lengkap operator precedence — php.net
- Dokumentasi operator aritmatika (termasuk **) — php.net
- Perubahan PHP 8.0 (precedence operator
.) — php.net
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
contoh.php
Unduh berkas<?php
// contoh.php — rangkuman Operator Precedence
// Jalankan dengan: php contoh.php
// 1. Perkalian menang lawan penjumlahan; tanda kurung menimpa urutan
echo "1 + 2 * 3 : " . (1 + 2 * 3) . "\n";
echo "(1 + 2) * 3 : " . ((1 + 2) * 3) . "\n";
// 2. Pangkat berasosiatif kanan; unary minus kalah dari **
echo "2 ** 3 ** 2 : " . (2 ** 3 ** 2) . "\n";
echo "(2 ** 3) ** 2 : " . ((2 ** 3) ** 2) . "\n";
echo "-2 ** 2 : " . (-2 ** 2) . "\n";
// 3. PHP 8: penjumlahan selesai sebelum penggabungan string
echo "\"sum: \" . 1 + 2 : " . ("sum: " . 1 + 2) . "\n";
echo "3 * 2 . \"!\" : " . (3 * 2 . "!") . "\n";
// 4. && lebih kuat dari ||
echo "true || false && false : ";
var_dump(true || false && false);
echo "(true || false) && false : ";
var_dump((true || false) && false);
// 5. and lebih lemah dari = (jebakan klasik)
$hasil1 = true and false;
$hasil2 = true && false;
echo "\$hasil1 = true and false : ";
var_dump($hasil1);
echo "\$hasil2 = true && false : ";
var_dump($hasil2);
// 6. Penugasan berasosiatif kanan
$x = $y = 5;
echo "x = $x, y = $y\n";
// 7. Tanda kurung untuk kejelasan
$umur = 25;
$status = ($umur >= 13 && $umur <= 19) ? "remaja" : "bukan remaja";
echo "Status: $status\n";