Anda sudah mengenal delapan tipe dasar PHP pada chapter-chapter sebelumnya — dan mungkin sempat menyadakan hal aneh: "5" + 3 di PHP tidak error, melainkan menghasilkan 8. Konversi tipe otomatis yang mengikuti konteks operasi inilah yang disebut type juggling. PHP tidak menuntut tipe cocok sebelum operasi berjalan; interpreter memilih tipe hasil mengikuti operator yang sedang bekerja. Keluwesan ini membuat kode singkat, tetapi juga menjadi sumber bug halus jika aturannya tidak dipahami — Chapter ini memetakan aturan tersebut satu per satu, dan setiap perilaku yang dibahas telah diuji langsung pada PHP 8.4.
Konversi Mengikuti Konteks Operasi #
Aturan pertamanya sederhana: operator yang menentukan tipe hasil. Operator aritmetika bekerja di dunia angka, sehingga seluruh operannya diarahkan ke int atau float:
<?php
var_dump("5" + 3);
var_dump("3.5" + 1);
var_dump("1e2" + 0);
var_dump(3 + true, 3 + false);
var_dump(5 * null);Output yang Dihasilkan:
int(8)
float(4.5)
float(100)
int(4)
int(3)
int(0)Mari kita bedah tiap barisnya:
"5" + 3: string"5"dikonversi menjadi int5, hasilnyaint(8)— keduanya int, hasil pun int."3.5" + 1: string pecahan menjadi float3.5; cukup satu operan float untuk membuat hasilfloat(4.5)."1e2" + 0: notasi ilmiah dikenali sebagai100.0, sehingga hasilnyafloat(100).3 + true, 3 + false: bool dikonversi menjadi1dan0— hasilnyaint(4)danint(3).5 * null: null menjadi0tanpa peringatan apa pun, hasilnyaint(0).
Perhatikan pola pemilihan int lawan float pada hasil — aturan lengkapnya dibahas pada Chapter Floating-Point Numbers . Dua operan pertama juga menunjukkan mengapa masukan dari formulir web, yang selalu datang sebagai string, bisa langsung dihitung tanpa konversi manual.
Tiga Kelas String Numerik #
Saat string bertemu operator angka, PHP membagi string ke dalam tiga kelas — dan nasib operasi ditentukan kelasnya:
| Kelas | Contoh | Nasib di operasi aritmetika | is_numeric() |
|---|---|---|---|
| Numerik penuh | "42", " 42 ", "3.5", "1e3" | dikonversi mulus, spasi awal/akhir diabaikan | true |
| Numerik di awal | "5 kopi", "42abc" | bagian angka diambil, muncul Warning | false |
| Non-numerik | "kopi", "" | TypeError, program berhenti | false |
Simpan contoh berikut sebagai teks-angka.php lalu jalankan untuk melihat kelas pertama dan kedua beraksi:
<?php
var_dump(is_numeric("42"), is_numeric("1e3"), is_numeric("42 budi"), is_numeric(""));
var_dump("5 kopi" + 3);Output yang Dihasilkan:
bool(true)
bool(true)
bool(false)
bool(false)
Warning: A non-numeric value encountered in /home/z/my-project/php-course/content/php/tipe-data-dan-type-system/type-juggling/.verify_tmp.php on line 4
int(8)Empat jawaban pertama menegaskan bahwa is_numeric() hanya berkata true untuk string yang sepenuhnya angka — "42 budi" gagal meski diawali angka. Baris terakhir memperlihatkan kelas kedua: PHP mengambil bagian awal "5", menjumlahkannya dengan 3 menjadi int(8), tetapi menyertakan Warning: A non-numeric value encountered sebagai tanda bahwa ada bagian string yang dibuang. Kelas ketiga tidak sebaik hati — simpan berikut sebagai jumlah.php:
<?php
var_dump("kopi" + 3);Output yang Dihasilkan:
Fatal error: Uncaught TypeError: Unsupported operand types: string + int in /home/z/my-project/php-course/content/php/tipe-data-dan-type-system/type-juggling/.verify_tmp.php:2
Stack trace:
#0 {main}
thrown in /home/z/my-project/php-course/content/php/tipe-data-dan-type-system/type-juggling/.verify_tmp.php on line 2String yang sama sekali tidak mengandung angka tidak punya jalan masuk ke dunia aritmetika: PHP melempar TypeError dengan pesan Unsupported operand types: string + int dan menghentikan program. Aturan tegas ini adalah hadiah dari PHP 8 — di PHP 7, "kopi" + 3 masih dihitung sebagai 3 dengan peringatan kecil yang mudah terlewat.
Perbandingan == yang Cerdas di PHP 8 #
Operator perbandingan longgar == juga melakukan juggling, dan aturannya dirombak besar-besaran di PHP 8. Prinsip barunya: bila string numerik dibandingkan dengan angka, keduanya dibandingkan secara numerik; bila string tidak numerik, angkanya justru dikonversi menjadi string dan keduanya dibandingkan sebagai teks:
<?php
var_dump("42" == 42);
var_dump(" 42" == 42);
var_dump("1e2" == 100);
var_dump("42kopi" == 42);
var_dump("abc" == 0);
var_dump("" == 0);Output yang Dihasilkan:
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)Tiga baris pertama true karena perbandingan berlangsung secara numerik — bahkan " 42" yang diawali spasi dan "1e2" bernilai 100 tetap dikenali. Tiga baris terakhir false, dan inilah yang wajib dicermati: "42kopi" termasuk kelas numerik-di-awal sehingga dibandingkan sebagai teks "42kopi" lawan "42", sedangkan "abc" dan "" tidak numerik sehingga angka 0 diubah menjadi "0" lalu kalah sebagai teks. Pada PHP 7, "abc" == 0 bernilai true — perilaku legendaris yang melahirkan banyak bug keamanan; perombakan PHP 8 memutuskan bahwa string non-numerik tidak lagi “menurut” ke angka.
Juggling null #
Null ikut berjuggling mengikuti konteks: menjadi 0 di aritmetika, string kosong di penggabungan teks, dan false di konteks bool. Perilakunya saat dibandingkan dengan == pun punya satu kejutan:
<?php
var_dump(null == 0, null == "", null == "0", null == false);
var_dump(null + 1);
var_dump("Total: " . 15000);
var_dump("x" . true, "x" . null);Output yang Dihasilkan:
bool(true)
bool(true)
bool(false)
bool(true)
int(1)
string(12) "Total: 15000"
string(2) "x1"
string(1) "x"Baris pertama memperlihatkan null setara dengan 0, string kosong, dan false — tetapi tidak dengan "0", karena string "0" bukan string kosong meskipun bernilai falsy. Baris kedua menegaskan null menjadi 0 di aritmetika. Dua baris terakhir memperlihatkan konteks string: operator titik (.) mengonversi operan apa pun menjadi teks — 15000 menjadi "15000", true menjadi "1", sedangkan null dan false menjadi string kosong. Aturan truthiness di balik perilaku ini dibahas pada Chapter Booleans
, dan makna null sebagai “tidak ada nilai” pada Chapter null
.
Kapan Juggling Menjadi Jebakan #
Juggling berbahaya justru karena nyaman: semuanya berjalan sampai tiba-tiba tidak. Masukan $_GET dan $_POST selalu berupa string, sehingga "5" dari URL bisa lolos ke perhitungan hari ini, lalu "5 kopi" memicu Warning minggu depan, dan "kopi" menjatuhkan program dengan TypeError bulan berikutnya. Perbandingan == pada data eksternal membuka celah yang lebih halus lagi, karena string yang “mirip angka” dan yang tidak dibedakan secara berbeda.
Pertahanan yang dianjurkan berlapis tiga: validasi masukan sebelum dipakai, bandingkan dengan === untuk data eksternal, dan nyalakan strict_types pada fungsi agar batas tipe ditegakkan di gerbang, bukan di tengah perhitungan. Namun seringkali langkah terbaik justru mengambil alih konversi secara sadar — mengubah string menjadi int tepat ketika kita tahu konversi itu memang dimaksudkan. Cara mengambil alih itu bernama type casting, dan itulah materi Chapter berikutnya.
Ringkasan #
Type juggling mengonversi nilai mengikuti konteks operasi: aritmetika mengarahkan string numerik, bool, dan null ke angka; string dibagi tiga kelas yang menentukan nasibnya dari konversi mulus, Warning, hingga TypeError; dan == di PHP 8 membandingkan string numerik secara angka tetapi menolak memaksa string non-numerik. Null berjuggling menjadi 0, "", atau false sesuai konteks, namun tetap tidak sama dengan "0". Dengan aturan-aturan ini terpetakan, kita siap memegang kendali konversi secara eksplisit lewat operator type casting.