PHP Döngüleri: for, while, foreach ve Akış Kontrolü

PHP Döngüleri: for, while, foreach ve Akış Kontrolü

4 dakika okuma

Döngü, bir kod bloğunu koşul sağlandığı sürece tekrar çalıştırır. PHP dört döngü yapısı sunar ve aralarındaki fark tekrar sayısının önceden bilinip bilinmemesine dayanır. Yanlış yapının seçilmesi çoğu zaman çalışan ama gereksiz yere karmaşık koda yol açar.

for: tekrar sayısı belliyse

Sayacın başlangıcı, bitiş koşulu ve artış miktarı tek satırda tanımlanır. Tekrar sayısının önceden bilindiği durumlar için uygundur:

PHP3 satır
for ($i = 1; $i <= 5; $i++) {
    echo "Satır {$i}" . PHP_EOL;
}

Bitiş koşulunda fonksiyon çağrısı yapmaktan kaçınmak gerekir. $i < count($dizi) yazıldığında count her adımda yeniden çalışır; değer döngü öncesinde bir değişkene alınmalıdır.

PHP5 satır
$adet = count($dizi);

for ($i = 0; $i < $adet; $i++) {
    islem($dizi[$i]);
}

Sayacın döngü dışında da gerekli olduğu durumlar dışında, indeksle gezinmek yerine foreach tercih edilir. İndeks hatası, dizinin sonunu bir eleman aşmak gibi klasik sorunların büyük kısmı bu tercihle ortadan kalkar.

while ve do-while: koşula bağlı tekrar

while, koşulu her tekrardan önce kontrol eder. Koşul en baştan yanlışsa gövde hiç çalışmaz. do-while ise gövdeyi önce çalıştırır, koşulu sonra bakar; yani en az bir kez çalışması garanti edilir:

PHP11 satır
$satir = fgets($dosya);
while ($satir !== false) {
    islem(trim($satir));
    $satir = fgets($dosya);
}

$deneme = 0;
do {
    $sonuc = baglan();
    $deneme++;
} while ($sonuc === false && $deneme < 3);

while kullanılan yerlerde döngüyü sonlandıracak değişikliğin gövde içinde mutlaka yapılması gerekir. Aksi halde sonsuz döngü oluşur ve betik zaman aşımına kadar çalışır.

foreach: diziler ve nesneler

Dizilerde tercih edilecek yapı foreach'tir. İndeks yönetimi gerektirmez ve ilişkisel dizilerde anahtarı da verir:

PHP5 satır
$fiyatlar = ['kalem' => 12.5, 'defter' => 34.0];

foreach ($fiyatlar as $urun => $fiyat) {
    printf('%s: %.2f TL%s', $urun, $fiyat, PHP_EOL);
}

Dizinin elemanlarını döngü içinde değiştirmek gerekiyorsa referans kullanılır. Referansla döngüden sonra değişkenin unset edilmemesi, sonraki döngülerde son elemanın bozulmasına yol açan klasik bir hatadır:

PHP4 satır
foreach ($sayilar as &$sayi) {
    $sayi *= 2;
}
unset($sayi);

break ve continue ile akış kontrolü

break döngüyü tamamen sonlandırır, continue yalnızca o adımı atlar. İç içe döngülerde her ikisi de sayı parametresi alarak birden fazla seviyeyi etkileyebilir:

PHP11 satır
foreach ($siparisler as $siparis) {
    if ($siparis['durum'] === 'iptal') {
        continue;
    }

    if ($siparis['tutar'] > $limit) {
        break;
    }

    isle($siparis);
}

İç içe döngüler ve maliyet

İç içe iki döngü, eleman sayısının karesiyle orantılı işlem üretir. Bin elemanlı iki dizi karşılaştırıldığında bir milyon adım oluşur. Bu tür karşılaştırmalar için dizinin anahtar üzerinden indekslenmesi çok daha hızlı sonuç verir:

PHP10 satır
// yavaş: her eleman için tüm diziyi tara
foreach ($a as $x) {
    if (in_array($x, $b, true)) { /* ... */ }
}

// hızlı: anahtar araması sabit zamanlı
$indeks = array_flip($b);
foreach ($a as $x) {
    if (isset($indeks[$x])) { /* ... */ }
}

Döngü yerine dizi fonksiyonu

Her tekrar eden iş döngü gerektirmez. Filtreleme, dönüştürme ve toplama işlemleri için hazır dizi fonksiyonları hem daha kısa hem de niyeti daha açık ifade eder. Aşağıdaki iki blok aynı sonucu üretir:

PHP10 satır
// döngüyle
$aktifler = [];
foreach ($kullanicilar as $k) {
    if ($k['aktif']) {
        $aktifler[] = $k;
    }
}

// dizi fonksiyonuyla
$aktifler = array_filter($kullanicilar, fn(array $k): bool => $k['aktif']);

Döngü, işin içinde koşullu erken çıkış ya da birden fazla yan etki varsa hâlâ daha okunur kalır. Seçim, kodun kısalığından çok neyi anlattığına göre yapılmalıdır.

Sonsuz döngü ve zaman aşımı

Sonsuz döngü genellikle koşulu değiştiren satırın unutulmasından ya da koşulun hiç sağlanamayacak biçimde yazılmasından kaynaklanır. Web isteğinde betik max_execution_time sınırına kadar çalışır ve sonra kesilir; komut satırında ise bu sınır varsayılan olarak yoktur, süreç elle durdurulana kadar devam eder.

Dış kaynağa bağlı bekleyen döngülerde güvenlik payı bırakmak gerekir. Deneme sayısına üst sınır koymak, hem sonsuz bekleyişi hem de karşı tarafa gereksiz yük binmesini engeller:

PHP13 satır
$deneme = 0;
$enFazla = 5;

while ($deneme < $enFazla) {
    $sonuc = istekGonder();

    if ($sonuc !== false) {
        break;
    }

    $deneme++;
    sleep(2 ** $deneme);
}

Kontrol listesi

  • Tekrar sayısı biliniyorsa for, dizide geziliyorsa foreach kullanılır.
  • Döngü koşulunda fonksiyon çağrısı bırakılmaz.
  • Referanslı foreach sonrasında değişken unset edilir.
  • Döngü içinde veritabanı sorgusu çalıştırmaktan kaçınılır; sorgu tek seferde yapılıp sonuç dizide gezilir.
  • İç içe döngü yerine anahtar tabanlı arama tercih edilir.

PHP eğitim serisi

Bu yazı, temel sözdiziminden üretim ortamına kadar ilerleyen 25 bölümlük serinin bir parçası. Bölümler sırayla okunacak biçimde hazırlandı, ancak her biri tek başına da kullanılabilir.

Temeller

  1. Kurulum ve temel sözdizimi
  2. Döngüler ve akış kontrolü (bu yazı)
  3. Diziler
  4. Fonksiyonlar
  5. String fonksiyonları
  6. Süper globaller
  7. Form işleme
  8. Dosya işlemleri

Dilin ayrıntıları

  1. Tip sistemi ve strict_types
  2. Hata ve istisna yönetimi
  3. Düzenli ifadeler
  4. Tarih ve saat işlemleri

Nesne yönelimli PHP

  1. Sınıf ve nesne
  2. Kalıtım, arayüz ve trait
  3. Statik üyeler, sabitler ve enum
  4. Namespace, Composer ve autoload

Veri ve güvenlik

  1. PDO ile veritabanı işlemleri
  2. Oturum yönetimi ve kimlik doğrulama
  3. Güvenli çıktı ve XSS
  4. JSON ile veri değişimi

Dış dünya ve üretim

  1. cURL ile dış API çağırma
  2. Kendi REST API'ni yazmak
  3. PHPUnit ile birim test
  4. Hata ayıklama ve performans ölçümü
  5. Üretime alma ve güvenlik

Yorumlar

Bu form reCAPTCHA ile korunur; Google Gizlilik Politikası ve Hizmet Şartları geçerlidir.

İlk yorumu sen yap.

İlgili Yazılar