Topik ini membahas switch sebagai bentuk percabangan warisan (legacy) beserta pernyataan break yang menyertainya, lalu beralih ke perulangan for, while, do-while, dan foreach. Pengendalian perulangan dengan break dan continue dibahas bersama contoh for, dan bagian akhir menyingkap jebakan referensi pada foreach beserta cara memutusnya. Setelah topik ini dipelajari, struktur perulangan yang tepat untuk sebuah tugas dapat dipilih dengan alasan yang jelas.
Switch warisan dan fallthrough#
Pernyataan switch membandingkan sebuah ekspresi dengan sejumlah case, yaitu label nilai yang diuji, menggunakan perbandingan lemah yang setara dengan operator ==. Bila nilai keduanya sama, seluruh pernyataan pada case itu dijalankan sampai ditemukan break yang menghentikan switch. Bila break tidak dituliskan, eksekusi menembus ke case berikutnya, dan perilaku ini disebut fallthrough. Cabang yang menampung sisanya dituliskan sebagai default.
<?php
$hari = 'Sabtu';
switch ($hari) {
case 'Senin':
case 'Selasa':
case 'Rabu':
case 'Kamis':
case 'Jumat':
$kategori = 'Hari kerja';
break;
case 'Sabtu':
case 'Minggu':
$kategori = 'Akhir pekan';
break;
default:
$kategori = 'Nama hari tidak dikenal';
break;
}
echo "$hari: $kategori", PHP_EOL;Sabtu: Akhir pekanCase Senin sampai Jumat dituliskan bertumpuk tanpa isi, sehingga kelimanya jatuh ke satu blok yang sama. Inilah penggunaan fallthrough yang disengaja, yaitu memetakan beberapa masukan ke satu hasil. Bila case dan hasilnya berpasangan satu-satu, setiap case diakhiri break agar case berikutnya tidak ikut terjalankan.
<?php
$tingkat = 2;
// tanpa break, eksekusi jatuh ke case berikutnya
switch ($tingkat) {
case 1:
echo 'Dasar', PHP_EOL;
case 2:
echo 'Menengah', PHP_EOL;
case 3:
echo 'Mahir', PHP_EOL;
break;
default:
echo 'Tidak dikenal', PHP_EOL;
}Menengah
MahirKeluaran di atas memperlihatkan $tingkat bernilai 2 menjalankan case 2, lalu karena tidak ada break, eksekusi berlanjut ke case 3 dan mencetak Mahir juga. Baru break pada case 3 menghentikan switch, sehingga default tidak tersentuh. Karena tidak ada error yang muncul, kebiasaan menutup setiap case dengan break menjadi pencegahan yang paling andal.
Perulangan for#
Perulangan for mengulang sebuah blok selama kondisinya bernilai true, dengan tiga ekspresi di dalam tanda kurungnya, yaitu inisialisasi variabel kendali, kondisi, dan perubahan variabel kendali. Inisialisasi dieksekusi sekali di awal, kondisi diuji sebelum setiap putaran, dan perubahan dijalankan setelah tubuh blok selesai. Bentuk ini paling tepat bila jumlah putaran sudah dapat dihitung sebelum perulangan dimulai.
<?php
$total = 0;
for ($i = 1; $i <= 100; $i++) {
$total += $i;
}
echo "Jumlah angka 1 sampai 100: $total", PHP_EOL;Jumlah angka 1 sampai 100: 5050Perulangan tersebut menambahkan $i ke $total seratus kali, dan hasilnya 5050 dapat dihitung ulang secara manual. Variabel kendali $i hanya berperan di dalam perulangan ini dan tidak dipakai lagi setelah perulangan selesai. Dua pernyataan mengendalikan jalannya perulangan, yaitu break yang menghentikannya seketika dan continue yang melompat ke putaran berikutnya, sebagaimana contoh berikut.
<?php
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 === 0) {
continue; // lewati angka genap
}
if ($i > 7) {
break; // berhenti sebelum mencapai 8
}
echo "$i ";
}
echo PHP_EOL;1 3 5 7Pernyataan continue membatalkan sisa tubuh blok untuk angka genap, sedangkan break menghentikan perulangan begitu $i bernilai 9. Keluarannya berhenti pada 7 karena 8 dilewati continue dan 9 langsung memenuhi kondisi break. Bila kedua pernyataan itu dihapus, seluruh angka 1 sampai 10 tercetak.
while dan do-while#
Perulangan while hanya memuat kondisi. Kondisi diuji sebelum setiap putaran, dan tubuhnya dijalankan selama kondisi bernilai true. Bila kondisi langsung bernilai false sejak awal, tubuhnya tidak dijalankan sama sekali. Bentuk ini cocok untuk tugas yang jumlah putarannya ditentukan oleh keadaan, bukan oleh penghitung.
<?php
$cetak = 3;
while ($cetak > 0) {
echo "Cetak ke-$cetak", PHP_EOL;
$cetak--;
}
echo "Selesai", PHP_EOL;Cetak ke-3
Cetak ke-2
Cetak ke-1
SelesaiKondisi $cetak > 0 menghasilkan true tiga kali, dan perulangan berhenti setelah $cetak mencapai 0. Pengurangan $cetak-- di dalam tubuh memastikan kondisi pada akhirnya bernilai false. Kelupaan menuliskan perubahan semacam ini memicu perulangan tak berujung sebagaimana dibahas pada bagian kesalahan umum. Perulangan do-while membalik urutan pengujian tersebut, yaitu tubuh dijalankan lebih dulu dan kondisi diuji sesudahnya, sehingga tubuh pasti dijalankan minimal satu kali.
Baris penutup do-while diakhiri titik koma setelah tanda kurungnya, dan kelupaan tanda ini memicu error sintaks ketika berkas dijalankan. Susunan yang menguji kondisi sesudah tubuh juga menuntut agar variabel yang dirujuk kondisi sudah terdefinisi sebelum blok dimasuki, sebagaimana $saldo pada contoh berikut.
<?php
$saldo = 0;
// kondisi awal sudah bernilai false, tetapi tubuh tetap dijalankan sekali
do {
echo "Tubuh dijalankan, saldo: $saldo", PHP_EOL;
$saldo += 50;
} while ($saldo > 100);Tubuh dijalankan, saldo: 0Kondisi $saldo > 100 bernilai false sejak awal, tetapi tubuh tetap tercetak satu kali. Urutan pengujian itulah satu-satunya pembeda do-while dari while, sehingga pemilihannya hanya relevan bila putaran pertama wajib terjadi, misalnya untuk menampilkan menu sebelum meminta pilihan.
foreach dan jebakan referensi#
Perulangan foreach didedikasikan untuk array dan mengiterasi nilainya satu per satu tanpa variabel kendali manual. Array adalah struktur data terurut yang menyimpan sekumpulan nilai. Bentuk pertama foreach mengambil nilai saja dengan pola foreach ($array as $nilai), sedangkan bentuk kedua mengambil kunci dan nilai sekaligus dengan pola foreach ($array as $kunci => $nilai). Contoh berikut membaca daftar stok yang memetakan nama bahan ke jumlahnya.
<?php
$stok = ['kertas' => 40, 'tinta' => 12, 'amplop' => 75];
foreach ($stok as $bahan => $jumlah) {
echo "$bahan: $jumlah", PHP_EOL;
}kertas: 40
tinta: 12
amplop: 75Mengubah elemen array dari dalam foreach memerlukan referensi, yaitu tanda & sebelum variabel nilainya. Referensi membuat $nilai menunjuk ke elemen aslinya, sehingga penugasan ke $nilai ikut mengubah array tersebut. Setelah perulangan berakhir, $nilai masih menjadi referensi ke elemen terakhir, dan di sinilah jebakannya.
<?php
$suhu = [24.0, 31.5, 22.8];
foreach ($suhu as &$nilai) {
$nilai += 0.5;
}
// $nilai masih menjadi referensi ke elemen terakhir array
$nilai = 100.0;
echo "Tanpa unset:", PHP_EOL;
print_r($suhu);
unset($nilai);
$suhu = [24.0, 31.5, 22.8];
foreach ($suhu as &$nilai) {
$nilai += 0.5;
}
unset($nilai);
$nilai = 100.0;
echo "Dengan unset:", PHP_EOL;
print_r($suhu);Tanpa unset:
Array
(
[0] => 24.5
[1] => 32
[2] => 100
)
Dengan unset:
Array
(
[0] => 24.5
[1] => 32
[2] => 23.3
)Bagian pertama keluaran memperlihatkan elemen ketiga berubah menjadi 100, padahal penugasan $nilai = 100.0 dituliskan setelah perulangan selesai. Penyebabnya, $nilai masih menjadi referensi ke elemen terakhir array, sehingga penugasan biasa ikut mengubah array itu. Memanggil unset($nilai) tepat setelah foreach memutus referensinya, dan bagian kedua keluaran membuktikan array tidak tersentuh setelah referensinya diputus.
Kesalahan umum#
Perulangan tak berujung terjadi bila kondisinya tidak pernah bernilai false, misalnya karena variabel kendali lupa diubah atau perubahannya justru menjauh dari batas. Skrip yang mengalaminya tidak pernah selesai dan harus dihentikan paksa, sehingga contoh berikut tidak dijalankan di sandbox.
// tidak-dijalankan: perulangan ini tidak pernah berhenti
while (true) {
echo 'berulang tanpa akhir';
}Kesalahan kedua adalah mengira penugasan pada variabel foreach tanpa referensi ikut mengubah array. Tanpa tanda &, $nilai hanyalah salinan nilai elemen, sehingga perubahan di dalam tubuh hilang begitu putaran berikutnya dimulai. Perubahan elemen array memerlukan referensi &$nilai sebagaimana diperlihatkan pada contoh jebakan-referensi.php, disertai unset setelahnya.
Kesalahan ketiga kembali ke switch, yaitu lupa break yang sudah diperlihatkan pada contoh lupa-break.php. Perlu diingat pula bahwa switch membandingkan secara lemah, sehingga string '1' cocok dengan case bernilai 1. Bila pemetaan membutuhkan kecocokan ketat, gunakan ekspresi match sebagai gantinya.
Perbandingan switch terhadap string juga peka huruf besar dan kecil, sehingga case 'Sabtu' tidak menangkap masukan 'sabtu'. Ubah masukan teks menjadi huruf kecil dengan strtolower() sebelum masuk ke switch, atau daftarkan semua bentuk tulisan yang mungkin pada case yang ditumpuk.
Ringkasan#
- switch membandingkan secara lemah dan menembus ke case berikutnya bila break tidak dituliskan, sedangkan case bertumpuk memanfaatkan penembusan itu secara disengaja.
- for mengulang dengan variabel kendali dan cocok untuk jumlah putaran yang sudah pasti, sedangkan while menguji kondisi sebelum tubuh dan do-while mengujinya sesudahnya sehingga tubuh minimal sekali dijalankan.
- foreach mengiterasi array dalam bentuk nilai saja maupun kunci dan nilai, dan perubahan elemen memerlukan referensi.
- Referensi
&$nilaitetap menempel pada elemen terakhir setelah perulangan selesai, sehingga unset dituliskan bila referensi tidak dipakai lagi.
Referensi#
- Pernyataan switch — PHP Manual — Dokumentasi resmi switch beserta break, default, dan perilaku fallthrough-nya.
- Perulangan for — PHP Manual — Dokumentasi perulangan for beserta penjelasan ketiga ekspresinya.
- Perulangan while — PHP Manual — Dokumentasi perulangan while dengan pengujian kondisi sebelum tubuh.
- Perulangan do-while — PHP Manual — Dokumentasi perulangan do-while yang menjalankan tubuh minimal sekali.
- Perulangan foreach — PHP Manual — Dokumentasi foreach beserta iterasi dengan referensi dan peringatannya.