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
<?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:

text
int(8)
float(4.5)
float(100)
int(4)
int(3)
int(0)

Mari kita bedah tiap barisnya:

  1. "5" + 3: string "5" dikonversi menjadi int 5, hasilnya int(8) — keduanya int, hasil pun int.
  2. "3.5" + 1: string pecahan menjadi float 3.5; cukup satu operan float untuk membuat hasil float(4.5).
  3. "1e2" + 0: notasi ilmiah dikenali sebagai 100.0, sehingga hasilnya float(100).
  4. 3 + true, 3 + false: bool dikonversi menjadi 1 dan 0 — hasilnya int(4) dan int(3).
  5. 5 * null: null menjadi 0 tanpa peringatan apa pun, hasilnya int(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:

KelasContohNasib di operasi aritmetikais_numeric()
Numerik penuh"42", " 42 ", "3.5", "1e3"dikonversi mulus, spasi awal/akhir diabaikantrue
Numerik di awal"5 kopi", "42abc"bagian angka diambil, muncul Warningfalse
Non-numerik"kopi", ""TypeError, program berhentifalse

Simpan contoh berikut sebagai teks-angka.php lalu jalankan untuk melihat kelas pertama dan kedua beraksi:

php
<?php
var_dump(is_numeric("42"), is_numeric("1e3"), is_numeric("42 budi"), is_numeric(""));

var_dump("5 kopi" + 3);

Output yang Dihasilkan:

text
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
<?php
var_dump("kopi" + 3);

Output yang Dihasilkan:

text

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 2

String 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
<?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:

text
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
<?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:

text
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.

Referensi #