foreach ($array as $value) bloğu her eleman için bir kez çalıştırır ve $value o anki eleman olur. Anahtarı da almak için foreach ($array as $key => $value) yazın.
foreach anahtarları ne olursa olsun her dizide çalışır ve hiçbir zaman bir sayaç yönetmez ya da uzunluk kontrol etmezsiniz. PHP'de en sık yazacağınız döngü budur.
Anahtarlar ve değerler üzerinde dolaşma
$key => $value içindeki isimleri siz seçersiniz: $name => $age, $id => $user, $k => $v. Bir listede anahtarlar 0, 1, 2 konumlarıdır. İlişkisel bir dizide (associative array) ise tanımladığınız dizge anahtarlardır.
Son döngü insanları şaşırtan bir ayrıntıyı gösterir: "1" gibi tam sayıya benzeyen bir dizge anahtar 1 tam sayısı olarak saklanır. "01" standart bir tam sayı değildir, bu yüzden dizge olarak kalır.
foreach içinde indeksi alma
Bir listede anahtar indekstir, bu yüzden foreach ($items as $i => $item) yeterlidir. İlişkisel bir dizide sayısal konum yoktur, bu yüzden bir sayaç tutun. İlk veya son elemana farklı davranmak için anahtarı array_key_first() veya array_key_last() ile karşılaştırın.
Son döngü isimler arasına virgül koyar ama sonuncudan sonra koymaz. Tam bu iş için implode(', ', array_keys($scores)) daha kısadır; array_key_last() kontrolü, son turun yalnızca farklı bir ayırıcı değil farklı bir mantık gerektirdiği durumlar içindir.
foreach içinde dizi değerlerini değiştirme (referansla)
$value bir kopyadır. Ona atama yapmak dizide hiçbir şeyi değiştirmez. Diziyi değiştirmek için ya &$value ile referansla dolaşın ya da anahtar üzerinden geri yazın.
İkisi de çalışır. Anahtarlı sürüm döngüden sonra gizli bir durum bırakmaz, birçok ekibin onu tercih etmesinin nedeni budur. Bir diziyi değiştirmek yerine yeni bir dizi oluşturmak için array_map() başka bir seçenektir.
İlgili bir soru: döngü sırasında eleman eklerseniz ne olur? Düz bir foreach diziyi döngü başladığındaki haliyle dolaşır, bu yüzden içindeki $prices[] = ... ek turlar oluşturmaz. Referanslı bir döngü ise canlı diziyi dolaşır ve yeni elemanları da ziyaret eder.
Referanslı foreach ile unset() tuzağı
foreach ($arr as &$v) sonrasında $v değişkeni hâlâ dizinin son elemanına bir referanstır. Daha sonra $v ismini normal bir döngüde yeniden kullanırsanız her tur o son elemana yazar. Bunu çalıştırın ve son elemana bakın:
İkinci döngü $letters[2] yuvasına önce A, sonra B, sonra son elemanın kendi değerini atar ve son tura gelindiğinde o yuva zaten B tutmaktadır. Çözüm tek satırdır: her referanslı foreach döngüsünden hemen sonra unset($v); yazın.
foreach içinde break ve continue
break döngüden çıkar, continue bir sonraki elemana atlar. Yaygın bir kalıp aramadır: ihtiyacınızı bulana kadar dolaşın, sonra dizinin geri kalanı kontrol edilmesin diye break kullanın.
İç içe döngülerde break 2 iç döngüden ve onu saran döngüden çıkar, continue 2 ise dış döngünün bir sonraki turuna atlar.
İç içe diziler ve list() ile foreach
Veri satırları bir dizi içindeki dizilerdir. Satırlar üzerinde, sonra her satır üzerinde dolaşın ya da alanları dizi ayrıştırma ile doğrudan foreach satırında çıkarın: listeler için [$a, $b], ilişkisel satırlar için ['key' => $var]. list($a, $b), [$a, $b] yazımının eski biçimidir.
Ayrıştırma sayfası atlanan elemanlar ve iç içe kalıplar dahil [...] = söz dizimini daha ayrıntılı anlatır.
foreach ile HTML liste veya tablo oluşturma
Bir şablonda foreach (...): ve endforeach; ile iki noktalı biçim döngüyü etiketler arasında okunur tutar. Bu blok bir tablo oluşturur ve sütun başlıkları bağlantıdır: Page sekmesinde birine tıklayın, aynı betik $_GET['sort'] ayarlanmış olarak yeniden çalışır ve satırlar yeni bir sırayla gelir.
Bu bloktan kopyalanmaya değer iki alışkanlık: URL'den gelen sort değeri kullanılmadan önce izin verilen sütunlar listesiyle kontrol edilir ve kullanıcı metni içerebilecek, HTML'e yazdırılan her değer htmlspecialchars() üzerinden geçer.
null, boş dizi veya nesne üzerinde foreach
Boş bir dizi sorun değildir: gövde hiç çalışmaz. null, bir dizge veya bir sayı ise sorundur: PHP bir uyarı yazdırır ve döngüyü atlar. $tags = null; foreach ($tags as $tag) için şunu yazdırır:
Warning: foreach() argument must be of type array|object, null given in /var/www/html/index.php on line 4
Bu en çok bazen eksik olan verilerde olur, örneğin çözümlenmiş JSON'daki isteğe bağlı bir alan. ?? ile boş bir diziye geri dönün:
foreach ($data['tags'] ?? [] as $tag) {
echo $tag;
}
O mesajdaki object gerçektir: bir nesne üzerinde foreach, döngünün çalıştığı yerden görünen özelliklerini (sınıfın dışından public olanları) özellik adı anahtar olacak şekilde ziyaret eder. Iterator veya IteratorAggregate uygulayan sınıflar ve generator'lar bir foreach döngüsünün ne göreceğine kendileri karar verir.
foreach, for ve array_map karşılaştırması
| Kullanım | Ne zaman |
|---|---|
foreach | Anahtarıyla ya da anahtarsız her elemanı istiyorsunuz. Liste veya ilişkisel, her dizide çalışır. |
for | Sayıyorsunuz (1'den 100'e, her ikinci eleman) ya da indeksle komşulara ihtiyacınız var ($a[$i - 1]). Bkz. for döngüsü. |
array_map() | Her elemanı dönüştürerek yeni bir dizi oluşturuyorsunuz, çoğu zaman fn ile tek satırda. |
array_filter() | Yalnızca bir testi geçen elemanları tutuyorsunuz. |
Karar vermenin hızlı yolu: döngü gövdesi her eleman için yalnızca yeni bir değer hesaplıyorsa array_map(fn($x) => $x * 2, $a) bunu tek satırda söyler. Yan etkileri varsa (yazdırma, kaydetme, aynı anda birkaç şey sayma) ya da break gerekiyorsa foreach yazın.
Sıkça Sorulan Sorular
PHP foreach döngüsünde anahtarı ve değeri nasıl alırım?
=> biçimini kullanın: foreach ($array as $key => $value) { echo "$key: $value"; }. Düz bir listede anahtar indekstir (0, 1, 2); ilişkisel bir dizide ise 'name' gibi dizge anahtardır.
PHP foreach döngüsünde indeksi nasıl alırım?
Bir listede anahtar zaten indekstir: foreach ($items as $i => $item). İlişkisel bir dizide kendi sayacınızı tutun: döngüden önce $i = 0;, her turun sonunda $i++. array_key_first() ve array_key_last() hangi anahtarın ilk ya da son olduğunu söyler.
PHP'de foreach içinde dizi değerlerini nasıl değiştiririm?
& ile referansla dolaşın: foreach ($prices as &$price) { $price *= 2; } unset($price);. Ya da anahtar üzerinden yazın: foreach ($prices as $key => $price) { $prices[$key] = $price * 2; }. Düz bir $price = ... yalnızca bir kopyayı değiştirir.
PHP'de referanslı foreach neden son elemanı tekrarlıyor?
foreach ($arr as &$v) sonrasında $v hâlâ son elemana bir referanstır. İkinci bir foreach ($arr as $v) her değeri o son yuvaya yazar, bu yüzden son yuva sondan bir önceki değeri tekrarlar hale gelir. Referanslı döngüden hemen sonra unset($v); çağırın.
PHP'de bir foreach döngüsünden nasıl çıkarım?
break; döngüyü hemen durdurur, continue; bir sonraki elemana atlar. İç içe döngülerde break 2; hem iç hem dış döngüden çıkar.