7-4: String Comparison
Objectives
- String comparison functions
- Natural sorting
- Similarity
- Memahami operator
==,===, dan<=> - Mengenal
version_comparedan keamanan output
Kenapa Perlu Membandingkan String?
Program sehari-hari penuh dengan perbandingan string: cek password, cek username, urutkan daftar nama, cari kata mirip untuk saran pencarian, sampai membandingkan versi aplikasi. PHP menyediakan banyak cara — dari operator sampai function khusus — dan masing-masing punya perilaku yang berbeda.
| Kebutuhan | Cara |
|---|---|
| Sama persis? | ===, strcmp() |
| Sama (abaikan case)? | strcasecmp() |
| Urutan alfabet? | strcmp(), <=> |
| Mirip? | similar_text(), levenshtein() |
| Versi software? | version_compare() |
Operator Perbandingan
Cara paling dasar membandingkan string adalah dengan operator:
<?php
$a = "apple";
$b = "apple";
$c = "Apple";
// == : sama (case-sensitive)
var_dump($a == $b); // Output: bool(true)
var_dump($a == $c); // Output: bool(false) — "apple" vs "Apple"
// === : sama dan tipe sama (string sama string)
var_dump($a === $b); // Output: bool(true)
// != dan !== : kebalikannya
var_dump($a != $c); // Output: bool(true)
var_dump($a !== $b); // Output: bool(false)
?>
Untuk string, == dan === hasilnya sama — string selalu string. Bedanya terasa saat membandingkan string dengan angka: "10" == 10 itu true (loose), tapi "10" === 10 itu false.
Spaceship Operator (<=>)
PHP 7+ punya operator <=> yang mengembalikan tiga kemungkinan nilai:
| Hasil | Arti |
|---|---|
-1 | Nilai kiri lebih kecil |
0 | Sama |
1 | Nilai kiri lebih besar |
<?php
echo "apple" <=> "banana"; // -1 (apple < banana)
echo "banana" <=> "apple"; // 1 (banana > apple)
echo "apple" <=> "apple"; // 0 (sama)
// Sangat berguna untuk callback sorting:
$buah = ["mangga", "apel", "jeruk", "pisang"];
usort($buah, fn($x, $y) => $x <=> $y);
print_r($buah);
// Output: ["apel", "jeruk", "mangga", "pisang"]
// Urutkan menurun: balik arahnya
usort($buah, fn($x, $y) => $y <=> $x);
print_r($buah);
// Output: ["pisang", "mangga", "jeruk", "apel"]
?>
Basic Comparison (Function)
Operator ==/=== hanya memberi tahu "sama atau tidak". Kalau kamu butuh urutan (mana yang lebih besar), gunakan strcmp:
<?php
$a = "apple";
$b = "banana";
// strcmp - binary safe
strcmp($a, $b); // < 0 (a < b)
strcmp($b, $a); // > 0 (b > a)
strcmp($a, $a); // 0 (equal)
// Case-insensitive
strcasecmp($a, "APPLE"); // 0
// First n characters
strncmp($a, $b, 3); // Compare first 3 chars
?>
| Fungsi | Membandingkan | Case-sensitive | Keterangan |
|---|---|---|---|
strcmp($a, $b) | Seluruh string | ✅ Ya | Binary safe |
strcasecmp($a, $b) | Seluruh string | ❌ Tidak | Abaikan besar/kecil |
strncmp($a, $b, $n) | $n karakter pertama | ✅ Ya | Partial |
strncasecmp($a, $b, $n) | $n karakter pertama | ❌ Tidak | Partial + case-insensitive |
Mengapa Hasilnya Bisa Negatif?
strcmp membandingkan berdasarkan nilai byte karakter: huruf kecil (a = 97) lebih besar dari huruf besar (A = 65). Perhatikan:
<?php
echo strcmp("apple", "Apple"); // 32 (a=97 vs A=65, selisih 32)
echo strcmp("a", "b"); // -1 (a < b)
echo strcmp("b", "a"); // 1 (b > a)
// "10" vs "9": karena string, bukan angka!
echo strcmp("10", "9"); // -8 ('1'=49 vs '9'=57, selisih -8)
echo (10 <=> 9); // 1 (10 > 9 secara angka)
?>
strcmp membandingkan secara string, bukan numerik. strcmp("10", "9") menghasilkan -1 karena karakter '1' lebih kecil dari '9'. Untuk angka, bandingkan sebagai angka (atau gunakan version_compare untuk versi).
Contoh Nyata: Sortir dengan strcmp
<?php
$nama = ["Budi", "andi", "Citra", "Andi"];
// sort() default: case-sensitive, huruf besar dulu
sort($nama);
print_r($nama);
// Output: ["Andi", "Budi", "Citra", "andi"]
// Dengan strcasecmp: abaikan case -> urutan alfabet murni
usort($nama, "strcasecmp");
print_r($nama);
// Output: ["andi", "Andi", "Budi", "Citra"]
?>
Natural Sorting
Sortir biasa (ASCII/byte order) menghasilkan urutan yang "aneh" untuk data berangka: file10 datang sebelum file2 karena '1' < '2'. Natural sort memperlakukan angka sebagai angka:
<?php
$files = ["file1.txt", "file10.txt", "file2.txt", "file21.txt"];
// Regular sort
sort($files);
print_r($files);
// file1.txt, file10.txt, file2.txt, file21.txt (ASCII order)
// Natural sort
natcasesort($files);
print_r($files);
// file1.txt, file2.txt, file10.txt, file21.txt (human order)
?>
| Fungsi | Perilaku |
|---|---|
sort() | Urutan byte/ASCII, file10 sebelum file2 |
natsort() | Natural, case-sensitive |
natcasesort() | Natural, case-insensitive — paling sering dipakai |
<?php
// natsort mengubah key array — reset dengan array_values
$versi = ["v1.10", "v1.9", "v1.2", "v2.0"];
natcasesort($versi);
$versi = array_values($versi); // rapi ulang index
print_r($versi);
// Output: ["v1.2", "v1.9", "v1.10", "v2.0"]
?>
Gunakan natcasesort untuk daftar file, nama produk dengan angka (Produk 2, Produk 10), atau versi — hasilnya sesuai intuisi manusia.
version_compare untuk Versi Software
Untuk membandingkan versi dengan benar (1.10 > 1.9), jangan pakai strcmp:
<?php
// version_compare($v1, $v2) -> -1, 0, atau 1
echo version_compare("1.10", "1.9"); // 1 (1.10 lebih baru)
echo version_compare("2.0", "2.0"); // 0 (sama)
echo version_compare("1.0", "1.1"); // -1 (1.0 lebih lama)
// Operator string juga didukung:
if (version_compare(PHP_VERSION, "8.0", ">=")) {
echo "Pakai match expression!"; // Output: Pakai match expression!
}
// Cocok untuk cek minimum requirement:
$requirement = "8.1";
if (version_compare(PHP_VERSION, $requirement, ">=")) {
echo "PHP kamu mendukung fitur ini";
} else {
echo "Upgrade PHP minimal $requirement";
}
?>
String Similarity
Kadang kita butuh mengukur seberapa mirip dua string — misalnya untuk fitur "mungkin maksudmu...":
<?php
$word1 = "PHP";
$word2 = "PHP";
similar_text($word1, $word2, $percent);
echo $percent; // 100
similar_text("PHP", "PHP", $p); // 100
similar_text("PHP", "PhP", $p); // ~66.67 (case-insensitive by default)
similar_text("hello", "helo", $p); // Different lengths
// Levenshtein distance
levenshtein("hello", "helo"); // 1 (one character difference)
?>
similar_text vs levenshtein
| Fungsi | Arti hasil | Kasus pakai |
|---|---|---|
similar_text | Persentase kemiripan (0-100) | Saran "apakah maksudmu?" |
levenshtein | Jumlah edit minimal (ganti/tambah/hapus) | Deteksi typo, autocorrect |
<?php
$kata = "teknilogi"; // typo, seharusnya "teknologi"
$kandidat = ["teknologi", "teknisi", "teknik"];
// Cari kandidat dengan jarak Levenshtein terkecil
$terbaik = null;
$jarak_terkecil = PHP_INT_MAX;
foreach ($kandidat as $c) {
$jarak = levenshtein($kata, $c);
if ($jarak < $jarak_terkecil) {
$jarak_terkecil = $jarak;
$terbaik = $c;
}
}
echo "Mungkin maksudmu: $terbaik (jarak $jarak_terkecil)";
// Output: Mungkin maksudmu: teknologi (jarak 1)
?>
levenshtein hanya bekerja untuk string ASCII. Untuk teks multibyte atau kebutuhan fuzzy search yang serius, pertimbangkan library seperti nlpTools atau pencarian full-text di database.
htmlspecialchars()
Saat menampilkan input user di halaman HTML, string bisa mengandung tag yang berbahaya. htmlspecialchars mengubah karakter khusus menjadi entity HTML sehingga browser menampilkannya sebagai teks biasa:
<?php
$user_input = '<script>alert("XSS")</script>';
// Escape HTML untuk output
$safe = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
echo $safe;
// Output: <script>alert("XSS")</script>
?>
Karakter yang di-escape:
| Karakter | Menjadi | Alasan |
|---|---|---|
< | < | Mencegah tag HTML dibaca |
> | > | Mencegah penutup tag |
& | & | Mencegah entity palsu |
" | " (dengan ENT_QUOTES) | Melindungi atribut HTML |
' | ' (dengan ENT_QUOTES) | Melindungi atribut HTML |
<?php
// Contoh di dunia nyata: komentar user
$komentar = "Bagus! <b>coba</b> <script>alert('x')</script>";
// ❌ Berbahaya: tag <script> akan dieksekusi browser
// echo $komentar;
// ✅ Aman: semua tag jadi teks biasa
echo htmlspecialchars($komentar, ENT_QUOTES, 'UTF-8');
// Output: Bagus! <b>coba</b> <script>alert('x')</script>
?>
Security: SELALU escape user input dengan htmlspecialchars() sebelum menampilkan di HTML untuk mencegah XSS attacks. Aturan emasnya: escape saat output, bukan saat input — karena konteks output menentukan escape yang tepat.
htmlspecialchars vs htmlentities vs strip_tags
| Fungsi | Perilaku | Kapan |
|---|---|---|
htmlspecialchars | Escape 5 karakter khusus | Default choice untuk output user |
htmlentities | Escape semua karakter yang punya entity | Teks dengan banyak simbol khusus |
strip_tags | Hapus tag (bukan escape) | Ingin teks polos tanpa HTML |
<?php
$teks = "<p>Harga: Rp 50.000 & gratis ongkir</p>";
// htmlspecialchars: cukup untuk keamanan
echo htmlspecialchars($teks, ENT_QUOTES, 'UTF-8');
// Output: <p>Harga: Rp 50.000 & gratis ongkir</p>
// strip_tags: buang tag, sisakan teks
echo strip_tags($teks);
// Output: Harga: Rp 50.000 & gratis ongkir
?>
Untuk output HTML yang aman, htmlspecialchars sudah cukup — tidak perlu htmlentities yang lebih berat. Yang wajib di-escape: <, >, &, dan kutip (jika di dalam atribut).
Common Mistakes
Mistake 1: Membandingkan string dengan == padahal butuh urutan
<?php
$kata1 = "pear";
$kata2 = "peach";
// == hanya jawab "sama/tidak"
var_dump($kata1 == $kata2); // bool(false)
// Untuk urutan, pakai strcmp / <=>
echo strcmp($kata1, $kata2); // 2 ("pear" > "peach" di karakter ke-3)
echo $kata1 <=> $kata2; // 1
?>
Mistake 2: Mengira strcmp mengembalikan boolean
<?php
// ❌ Salah: strcmp mengembalikan angka, bukan true/false
if (strcmp($a, $b)) {
// Ini jalan SAAT KEDUANYA BEDA (hasil != 0)
// — kebalikan dari yang mungkin kamu kira!
}
// ✅ Benar: bandingkan hasilnya dengan 0
if (strcmp($a, $b) === 0) {
// Sama
}
// Atau lebih sederhana untuk sekadar cek sama:
if ($a === $b) {
// Sama
}
?>
strcmp mengembalikan angka, bukan boolean — 0 artinya sama. if (strcmp($a, $b)) bernilai true justru saat string berbeda! Untuk sekadar cek kesamaan, === jauh lebih jelas.
Mistake 3: Menampilkan user input tanpa escape
<?php
// ❌ XSS vulnerability!
// echo $_GET["nama"];
// ✅ Aman
echo htmlspecialchars($_GET["nama"] ?? "", ENT_QUOTES, 'UTF-8');
?>
Mistake 4: Mengurutkan angka sebagai string
<?php
$nilai = ["10", "9", "100", "2"];
// ❌ Urutan string: "10" < "2" karena '1' < '2'
sort($nilai);
print_r($nilai);
// Output: ["10", "100", "2", "9"]
// ✅ Urutan natural: angka dibaca sebagai angka
natcasesort($nilai);
print_r(array_values($nilai));
// Output: ["2", "9", "10", "100"]
?>
Pro Tips
- Cek kesamaan ->
===; cek urutan ->strcmp/<=>; cek mirip ->similar_text/levenshtein. strcmphasilnya0= sama — jangan dibalik.natcasesortuntuk data campuran teks+angka (nama file, produk, versi).version_compareuntuk versi software — jangan pernahstrcmp.htmlspecialchars($x, ENT_QUOTES, 'UTF-8')sebelum echo — kebiasaan yang menyelamatkan dari XSS.<=>(spaceship) sangat praktis sebagai callbackusort.
Exercise
- Buat function untuk compare version strings (1.0 vs 1.1)
- Gunakan natural sort untuk filename list
- Kenapa htmlspecialchars() penting untuk keamanan?
- Tulis function
cari_terdekat(string $kata, array $kandidat): stringyang mengembalikan kandidat paling mirip menggunakanlevenshtein. - Urutkan array
["Buku 2", "Buku 10", "Buku 1", "Buku 21"]dengannatcasesortdan tampilkan hasilnya. - Tampilkan komentar user berikut dengan aman di HTML:
"<script>alert('hack')</script> Saya suka <b>PHP</b>!"— tunjukkan output yang aman.
Summary
| Kebutuhan | Alat | Hasil |
|---|---|---|
| Sama/tidak | ==, ===, !=, !== | boolean |
| Urutan | strcmp, strcasecmp, strncmp | -1 / 0 / 1 |
| Urutan ringkas | <=> (spaceship) | -1 / 0 / 1 |
| Sortir natural | natcasesort, natsort | array terurut |
| Versi software | version_compare | -1 / 0 / 1 |
| Kemiripan | similar_text (%), levenshtein (jarak) | angka |
| Output aman | htmlspecialchars | string ter-escape |
Klik tombol ini setelah menyelesaikan materi
Quiz Bab 7
Uji pemahamanmu tentang String Manipulation