3-4: Match Expression
Objectives
- Mengenal match expression (PHP 8+)
- Memahami perbedaannya dengan switch
- Keuntungan match expression
- Memahami strict comparison pada match
- Mengenal UnhandledMatchError dan cara menghindarinya
Pendahuluan: Evolusi dari Switch
switch sudah lama menjadi andalan untuk percabangan banyak nilai, tapi ia punya kelemahan: mudah lupa break, pakai perbandingan loose (==), dan tidak bisa langsung menghasilkan nilai. PHP 8 memperkenalkan match expression yang memperbaiki semua itu.
| Aspek | switch (PHP 5+) | match (PHP 8+) |
|---|---|---|
| Break | Wajib break; manual | Otomatis, tanpa break |
| Perbandingan | Loose (==) | Strict (===) |
| Nilai hasil | Statement, tidak bernilai | Expression, menghasilkan nilai |
| Eksekusi | Case dieksekusi berurutan | Hanya satu arm yang cocok |
match mirip switch, tapi alih-alih mengeksekusi blok kode, ia menghasilkan sebuah nilai — seperti ternary yang lebih kuat.
Basic Match
<?php
$grade = "A";
$result = match ($grade) {
"A" => "Excellent",
"B" => "Good",
"C" => "Average",
"D" => "Poor",
"F" => "Fail",
default => "Invalid grade",
};
echo $result; // Excellent
?>
Perhatikan perbedaan bentuk dengan switch:
| Aspek | Switch | Match |
|---|---|---|
| Penanda cabang | case "A": | "A" => |
| Pemecah | break; | Tidak ada (otomatis) |
| Nilai | Tidak menghasilkan | => menghasilkan nilai |
| Penutup | } | }; (titik koma!) |
| Default | default: | default => |
Jangan lupa titik koma setelah kurung tutup }; — match adalah expression, jadi ia diakhiri seperti statement biasa.
Match vs Switch
<?php
$day = "Monday";
// Switch
switch ($day) {
case "Monday":
case "Tuesday":
case "Wednesday":
case "Thursday":
case "Friday":
echo "Weekday";
break;
case "Saturday":
case "Sunday":
echo "Weekend";
break;
}
// Match (cleaner!)
$result = match ($day) {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday" => "Weekday",
"Saturday", "Sunday" => "Weekend",
};
echo $result; // Weekday
?>
Dua keunggulan langsung terlihat:
- Multi-value per arm — cukup pisahkan dengan koma, tanpa trik fall-through.
- Tanpa
break— setiap arm otomatis berhenti sendiri, tidak mungkin menetes.
Strict Comparison (===)
match menggunakan perbandingan strict (===). Ini perbedaan paling krusial dengan switch:
<?php
$value = "10"; // string
// Switch: loose — case 10 (int) yang cocok!
switch ($value) {
case 10:
echo "switch: int 10";
break;
case "10":
echo "switch: string 10";
break;
}
// Output: switch: int 10
// Match: strict — hanya "10" string yang cocok
$result = match ($value) {
10 => "match: int 10",
"10" => "match: string 10",
};
echo $result; // match: string 10
?>
Karena strict, match aman dipakai untuk membedakan 0, "0", "", dan null — empat nilai yang saling "menabrak" di switch.
Match dengan Conditions
match (true) memungkinkan kondisi boolean seperti if-elseif:
<?php
$number = 85;
$result = match (true) {
$number >= 90 => "A",
$number >= 80 => "B",
$number >= 70 => "C",
$number >= 60 => "D",
default => "E",
};
echo $result; // B
?>
Pola ini menggantikan rantai if-elseif dengan visualisasi kasus yang rapi. Kondisi dievaluasi dari atas ke bawah, dan arm pertama yang true yang menang.
Match dengan Ekspresi Kompleks
Karena arm match bisa berisi ekspresi apa pun, kita bisa melakukan lebih dari sekadar memilih literal:
<?php
$operasi = "tambah";
$hasil = match ($operasi) {
"tambah" => 5 + 3,
"kurang" => 5 - 3,
"kali" => 5 * 3,
"bagi" => 5 / 3,
default => throw new InvalidArgumentException("Operasi tidak dikenal"),
};
echo $hasil; // 8
?>
Perhatikan arm default yang melempar exception — ini pola yang sah dan sangat berguna. Di switch, kamu tidak bisa melempar exception sebagai "nilai default".
Match Harus Lengkap (Exhaustive)
Perbedaan paling penting dengan switch: jika tidak ada arm yang cocok dan tidak ada default, PHP melempar UnhandledMatchError — program berhenti dengan error.
<?php
$status = "pending";
// ❌ Tidak ada default: error UnhandledMatchError!
// $pesan = match ($status) {
// "active" => "User aktif",
// "inactive" => "User tidak aktif",
// };
// ✅ Selalu sediakan default
$pesan = match ($status) {
"active" => "User aktif",
"inactive" => "User tidak aktif",
default => "Status tidak dikenal",
};
echo $pesan; // Status tidak dikenal
?>
<?php
// Contoh error yang nyata:
function label_hari(string $hari): string
{
return match ($hari) {
"senin" => "Hari ke-1",
"selasa" => "Hari ke-2",
// lupa "rabu" sampai "minggu"!
};
}
// try {
// echo label_hari("rabu");
// } catch (UnhandledMatchError $e) {
// echo "Error: " . $e->getMessage();
// }
// Output: Error: Unhandled match value of type string
?>
Selalu sertakan default di match kecuali kamu yakin semua kemungkinan nilai sudah tercakup. Error UnhandledMatchError sering terjadi saat data datang dari luar (input user, API, database) yang nilainya tidak terduga.
Match Features
- Returns value
- No fall-through (semua cases harus covered atau ada default)
- Uses strict comparison (===)
- Can use multiple values per case
<?php
// Returns value - can assign directly
$color = "red";
$hex = match ($color) {
"red" => "#FF0000",
"green" => "#00FF00",
"blue" => "#0000FF",
};
echo $hex; // #FF0000
// No fall-through - default required
$status = "unknown";
$result = match ($status) {
"active" => "User aktif",
"inactive" => "User tidak aktif",
default => "Status tidak dikenal",
};
echo $result; // Status tidak dikenal
// Multiple values per arm
$hari = "Sabtu";
$jenis = match ($hari) {
"Senin", "Selasa", "Rabu", "Kamis", "Jumat" => "hari kerja",
"Sabtu", "Minggu" => "akhir pekan",
};
echo $jenis; // akhir pekan
?>
Match dengan Tipe Data Campuran
Karena match memakai ===, kita bisa membedakan tipe data dengan aman — sesuatu yang mustahil di switch:
<?php
function describe($nilai): string
{
return match (true) {
$nilai === null => "null",
$nilai === 0 => "integer nol",
$nilai === "0" => "string nol",
$nilai === "" => "string kosong",
$nilai === false => "boolean false",
is_int($nilai) => "integer: $nilai",
is_string($nilai) => "string: $nilai",
default => "tipe lain",
};
}
echo describe(null); // null
echo describe(0); // integer nol
echo describe("0"); // string nol
echo describe(""); // string kosong
echo describe(false); // boolean false
echo describe(42); // integer: 42
?>
Perhatikan urutan: kasus spesifik (null, 0, "0") diletakkan sebelum kasus umum (is_int, is_string) karena match mengambil arm pertama yang cocok.
Common Mistakes
Mistake 1: Lupa titik koma
<?php
$n = 1;
// ❌ Syntax error — match adalah expression, butuh ;
// $hasil = match ($n) { 1 => "satu" }
// ✅
$hasil = match ($n) {
1 => "satu",
};
echo $hasil; // satu
?>
Mistake 2: Mengharapkan perilaku fall-through
<?php
$nilai = 75;
// ❌ Salah: match TIDAK punya fall-through, setiap arm berdiri sendiri
// $hasil = match (true) {
// $nilai >= 60 => "Lulus",
// $nilai >= 80 => "Cumlaude", // tidak akan pernah tercapai!
// };
// ✅ Benar: urutkan dari kondisi paling spesifik
$hasil = match (true) {
$nilai >= 80 => "Cumlaude",
$nilai >= 60 => "Lulus",
default => "Tidak lulus",
};
echo $hasil; // Lulus
?>
Urutan arm sangat penting di match. Sama seperti elseif, arm pertama yang cocok yang menang. Kondisi spesifik harus diletakkan di atas kondisi umum.
Mistake 3: Mengira match bisa mengeksekusi banyak statement per arm
<?php
// ❌ Setiap arm hanya bisa menghasilkan SATU expression
// $hasil = match ($x) {
// 1 => { echo "satu"; $x * 2; }, // ❌ bukan syntax PHP
// };
// ✅ Solusi: bungkus logika dalam function/closure
$hitung = function (int $x): int {
echo "memproses $x\n";
return $x * 2;
};
$x = 3;
$hasil = match ($x) {
1 => $hitung(1),
2 => $hitung(2),
default => $hitung($x),
};
echo $hasil; // memproses 3\n6
?>
Match vs If-Else vs Switch — Kapan Pakai Apa?
| Kebutuhan | Pilih |
|---|---|
| Banyak nilai tetap, butuh hasil langsung | match |
| Perbandingan strict antar nilai | match |
Membedakan 0, "0", "", null | match |
| Banyak cabang yang mengeksekusi blok kode panjang | switch atau if-elseif |
Kondisi kompleks dengan &&, function calls | if-elseif |
| Kode harus jalan di PHP 7 | switch (match butuh PHP 8+) |
Pro Tips
- Match menggantikan 90% penggunaan switch di kode baru — lebih aman (strict) dan lebih ringkas.
- Selalu tambahkan
default, terutama untuk data dari luar sistem. - Urutkan arm dari kondisi paling spesifik ke paling umum.
- Gunakan
match (true)untuk menggantikan rantaiif-elseifyang panjang. default => throw new ...adalah pola valid untuk menolak nilai tak dikenal secara eksplisit.- Jika satu arm butuh lebih dari satu statement, ekstrak ke function dulu.
Exercise
- Convert switch ke match expression
- Buat match untuk HTTP status codes
- Kenapa match lebih aman dari switch?
- Tulis function
kategori_umur(int $umur): stringmenggunakanmatch (true)dengan aturan: 0-12 "Anak", 13-17 "Remaja", 18-59 "Dewasa", 60+ "Lansia". Sertakandefaultuntuk umur negatif. - Apa output kode berikut, dan kenapa?
<?php
$n = "10";
echo match ($n) {
10 => "int",
"10" => "string",
};
?>
Summary
| Konsep | Poin Kunci |
|---|---|
match | Expression PHP 8+ yang menghasilkan nilai |
| Arm | nilai => hasil, multi-value dipisah koma |
| Strict | Pakai ===, aman bedakan 0 vs "0" |
| Exhaustive | Tanpa default bisa lempar UnhandledMatchError |
| No fall-through | Setiap arm berhenti sendiri, tanpa break |
match (true) | Gantikan rantai if-elseif dengan kondisi boolean |
Klik tombol ini setelah menyelesaikan materi
Quiz Bab 3
Uji pemahamanmu tentang Struktur Kontrol