PHP'de bir dizinin her elemanını dönüştürmek için array_map(), koşula uyan elemanları ayırmak için array_filter(), bütün elemanları tek bir değere indirmek için array_reduce() kullanılır. Bir değer aramak için in_array() ve array_search(), koşula uyan ilk elemanı bulmak için ise PHP 8.4 ile gelen array_find() vardır. Bu fonksiyonların hepsi yeni bir dizi veya değer döndürür; asıl diziyi değiştirmez.
Bu yazıda en sık kullanılan dizi fonksiyonlarını, kılavuzda yazan ama gözden kaçan davranışlarıyla birlikte anlatıyoruz: hangisi anahtarları korur, hangisi gevşek karşılaştırma yapar, hangisi boş dizide null döndürür. Dizi sözdizimi ve anahtar kuralları PHP dizi temelleri yazısında, callback olarak kullandığımız fn ve anonim fonksiyonlar anonim fonksiyon ve arrow function yazısında ayrıca var.
Parametre sırasına dikkat

PHP'nin dizi fonksiyonları uzun bir geçmişe sahip olduğu için parametre sırası tutarlı değildir. array_map() önce callback'i, sonra diziyi alır; array_filter(), array_reduce() ve PHP 8.4'teki array_find() ailesi ise önce diziyi, sonra callback'i alır. Arama fonksiyonlarında da aranan değer (needle) önce, dizi (haystack) sonra gelir. Sırayı karıştırdığınızda PHP 8 bir TypeError verir, yani hata sessiz kalmaz; ama yazarken bu tabloyu akılda tutmak zaman kazandırır.
| Fonksiyon | İmza (sadeleştirilmiş) | Anahtarlar | Döndürdüğü |
|---|---|---|---|
| array_map | array_map(callback, dizi, ...diziler) | tek dizide korunur | yeni dizi |
| array_filter | array_filter(dizi, callback, mod) | korunur, boşluk kalabilir | yeni dizi |
| array_reduce | array_reduce(dizi, callback, baslangic) | kullanılmaz | tek değer |
| array_column | array_column(dizi, sutun, indeks) | korunmaz | yeni dizi |
| in_array | in_array(deger, dizi, strict) | kullanılmaz | bool |
| array_search | array_search(deger, dizi, strict) | ilk eşleşen anahtar | int, string veya false |
| array_find (8.4) | array_find(dizi, callback) | kullanılmaz | değer veya null |
| array_find_key (8.4) | array_find_key(dizi, callback) | ilk eşleşen anahtar | anahtar veya null |
array_map(): her elemanı dönüştürmek
array_map(), verdiğiniz callback'i dizinin her değerine uygular ve sonuçlardan yeni bir dizi kurar. Tek dizi verdiğinizde sonuç dizisi aynı anahtarları korur; bu, ilişkisel dizilerde değerleri dönüştürürken çok işe yarar. Callback yalnızca değeri alır, anahtarı almaz. Anahtara da ihtiyacınız varsa kılavuzun önerdiği yol, array_keys() ve array_values() sonuçlarını iki ayrı dizi olarak geçirmektir.
<?php
$fiyatlar = ['kalem' => 12.5, 'defter' => 30, 'silgi' => 7.25];
$kdvli = array_map(fn($f) => round($f * 1.2, 2), $fiyatlar);
print_r($kdvli);
/* çıktı:
Array
(
[kalem] => 15
[defter] => 36
[silgi] => 8.7
)
*/
$etiketler = array_map(
fn($urun, $fiyat) => "$urun: $fiyat TL",
array_keys($fiyatlar),
array_values($fiyatlar)
);
echo implode(' | ', $etiketler), "\n";
// çıktı: kalem: 12.5 TL | defter: 30 TL | silgi: 7.25 TLBirden fazla dizi verdiğinizde callback her dizinin aynı konumdaki elemanını ayrı parametre olarak alır. Bu durumda anahtarlar korunmaz, sonuç her zaman 0'dan başlayan bir liste olur. Diziler farklı uzunluktaysa kısa olanlar boş elemanlarla uzatılır, yani callback eksik konumlar için null alır. Callback yerine null verirseniz fonksiyon dizileri "fermuar" gibi birleştirir: her konum için elemanları bir alt dizide toplar.
<?php
$urunler = ['kalem', 'defter', 'silgi'];
$adetler = [3, 5];
$satirlar = array_map(fn($u, $a) => sprintf('%s x %s', $a ?? 0, $u), $urunler, $adetler);
echo implode(', ', $satirlar), "\n";
// çıktı: 3 x kalem, 5 x defter, 0 x silgi
echo json_encode(array_map(null, $urunler, $adetler)), "\n";
// çıktı: [["kalem",3],["defter",5],["silgi",null]]array_filter(): koşula uyanları ayırmak
array_filter() her değeri callback'e gönderir ve callback true döndürdüğü elemanları yeni diziye alır. Anahtarlar korunur; bu yüzden numaralı bir listeyi filtrelediğinizde sonuçta 0, 2, 5 gibi boşluklu anahtarlar kalabilir. Sonucu liste olarak kullanacaksanız, özellikle JSON'a çevirecekseniz, array_values() ile yeniden numaralayın.
Callback vermezseniz fonksiyon "boş" sayılan bütün değerleri atar: false, null, 0, '', '0' ve boş dizi. Bu kısa yol pratik görünse de '0' metnini ve 0 sayısını da sildiği için form verilerinde istenmeyen kayıplara yol açabilir. Üçüncü parametreyle callback'e ne gönderileceğini değiştirebilirsiniz: ARRAY_FILTER_USE_KEY yalnızca anahtarı, ARRAY_FILTER_USE_BOTH önce değeri sonra anahtarı gönderir.
<?php
$puanlar = [45, 82, 67, 91, 30];
$gecenler = array_filter($puanlar, fn($p) => $p >= 50);
echo json_encode($gecenler), "\n"; // çıktı: {"1":82,"2":67,"3":91}
echo json_encode(array_values($gecenler)), "\n"; // çıktı: [82,67,91]
$form = ['ad' => 'Deniz', 'kat' => '0', 'not' => '', 'yas' => null];
print_r(array_filter($form));
/* çıktı:
Array
(
[ad] => Deniz
)
*/
print_r(array_filter($form, fn($v) => $v !== null && $v !== ''));
/* çıktı:
Array
(
[ad] => Deniz
[kat] => 0
)
*/
$ayar = ['db_host' => 'localhost', 'db_ad' => 'magaza', 'cache' => 'redis'];
print_r(array_filter($ayar, fn($k) => str_starts_with($k, 'db_'), ARRAY_FILTER_USE_KEY));
/* çıktı:
Array
(
[db_host] => localhost
[db_ad] => magaza
)
*/array_reduce(): diziyi tek değere indirmek

array_reduce() callback'i her elemanla sırayla çağırır ve her çağrının sonucunu bir sonrakine $carry (taşınan değer) olarak verir. Üçüncü parametre başlangıç değeridir; ilk çağrıda $carry bu değeri alır, dizi boşsa sonuç doğrudan bu değer olur. Başlangıç değeri vermezseniz ve dizi boşsa fonksiyon null döndürür. Toplam veya çarpım hesaplarken başlangıç değerini her zaman açıkça yazmak, boş dizide null ile hesap yapma hatasını önler.
<?php
$sepet = [
['urun' => 'kalem', 'fiyat' => 12.5, 'adet' => 4],
['urun' => 'defter', 'fiyat' => 30, 'adet' => 2],
];
$toplam = array_reduce($sepet, fn($t, $s) => $t + $s['fiyat'] * $s['adet'], 0);
echo $toplam, "\n"; // çıktı: 110
var_dump(array_reduce([], fn($t, $s) => $t + $s)); // çıktı: NULL
var_dump(array_reduce([], fn($t, $s) => $t + $s, 0)); // çıktı: int(0)Basit toplamlar için array_sum() daha okunaklıdır. array_reduce(), sonucun bir dizi veya nesne olduğu durumlarda gerçek değerini gösterir; örneğin elemanları bir alana göre gruplamak gibi.
Aşağıdaki örnekte başlangıç değeri boş bir dizidir. Callback her kişiyi şehrine ait alt diziye ekler ve güncellenmiş diziyi geri döndürür. Callback'in $gruplar dizisini değiştirip döndürmesi şarttır; döndürmeyi unutursanız bir sonraki adımda $carry null olur ve gruplama bozulur. Bu, array_reduce() ile yazılan kodlarda en sık görülen hatadır.
<?php
$kisiler = [
['ad' => 'Ece', 'sehir' => 'İzmir'],
['ad' => 'Mert', 'sehir' => 'Bursa'],
['ad' => 'Sena', 'sehir' => 'İzmir'],
];
$gruplar = array_reduce($kisiler, function (array $gruplar, array $k): array {
$gruplar[$k['sehir']][] = $k['ad'];
return $gruplar;
}, []);
echo json_encode($gruplar, JSON_UNESCAPED_UNICODE), "
";
// çıktı: {"İzmir":["Ece","Sena"],"Bursa":["Mert"]}array_column(): tablodan sütun çekmek
Veritabanından gelen satırlar gibi "satır listesi" biçimindeki dizilerde tek bir alanın değerlerini almak için array_column() kullanılır. İkinci parametre çekilecek sütun, üçüncü parametre ise sonuç dizisinde anahtar olarak kullanılacak sütundur. İkinci parametreye null verirseniz satırların tamamı döner; bu, üçüncü parametreyle birlikte bir listeyi kimliğe göre anahtarlamanın kısa yoludur. Satırlar nesne de olabilir; o durumda public özellikler okunur. Sütunu olmayan satırlar uyarı verilmeden atlanır ve giriş dizisinin anahtarları hiçbir zaman korunmaz.
<?php
$kullanicilar = [
['id' => 7, 'ad' => 'Ece', 'rol' => 'editor'],
['id' => 12, 'ad' => 'Mert', 'rol' => 'admin'],
['id' => 15, 'ad' => 'Sena'],
];
echo json_encode(array_column($kullanicilar, 'ad')), "\n";
// çıktı: ["Ece","Mert","Sena"]
echo json_encode(array_column($kullanicilar, 'rol', 'id')), "\n";
// çıktı: {"7":"editor","12":"admin"}
$idye_gore = array_column($kullanicilar, null, 'id');
echo $idye_gore[12]['ad'], "\n";
// çıktı: Mertin_array() ve array_search(): değer aramak
in_array() değerin dizide olup olmadığını söyler, array_search() ise bulduğu ilk elemanın anahtarını döndürür. İkisi de üçüncü parametre true verilmedikçe gevşek karşılaştırma (==) yapar. PHP 8.0 bu konuda önemli bir şeyi düzeltti: sayı olmayan bir metin artık 0 ile eşleşmiyor. Ama gevşek karşılaştırma hâlâ şaşırtıcıdır: true boş olmayan her metinle, false ise hem '' hem de '0' ile eşleşir. Kılavuzun açık önerisi, değerlerin tiplerinden emin değilseniz her zaman strict parametresini true yapmaktır. Gevşek karşılaştırmanın genel kuralları PHP eşitlik ve karşılaştırma yazısında.
<?php
var_dump(in_array(0, ['aktif', 'pasif'])); // çıktı: bool(false) (PHP 8 ve sonrası)
var_dump(in_array('1', [1, 2, 3])); // çıktı: bool(true)
var_dump(in_array('1', [1, 2, 3], true)); // çıktı: bool(false)
var_dump(in_array(true, ['hayır'])); // çıktı: bool(true)
var_dump(in_array(true, ['hayır'], true)); // çıktı: bool(false)
var_dump(in_array(false, ['0'])); // çıktı: bool(true)array_search() ile ilgili en yaygın hata, dönüş değerini doğrudan if içinde kullanmaktır. Aranan değer 0 anahtarında bulunursa fonksiyon 0 döndürür ve bu değer if içinde yanlış (false) sayılır. Kılavuz bu yüzden sonucu === veya !== ile false'a karşı test etmenizi ister. Bir değerin geçtiği bütün anahtarları istiyorsanız array_keys($dizi, $deger) kullanın; bu da üçüncü parametreyle katı karşılaştırmaya geçebilir.
<?php
$sira = ['ali', 'veli', 'ali'];
if (array_search('ali', $sira)) {
echo "bulundu\n";
} else {
echo "bulunamadı\n"; // çıktı: bulunamadı (anahtar 0 olduğu için)
}
$k = array_search('ali', $sira);
if ($k !== false) {
echo "anahtar: $k\n"; // çıktı: anahtar: 0
}
echo implode(',', array_keys($sira, 'ali')), "\n"; // çıktı: 0,2Callback olarak neler verebilirsiniz?
Bu fonksiyonların callback parametresi callable tipindedir; yani yalnızca fn ile yazılmış kısa fonksiyonları değil, çağrılabilir her değeri kabul eder. Hazır bir PHP fonksiyonunun adını metin olarak verebilirsiniz: array_map('trim', $dizi) her elemanın başındaki ve sonundaki boşlukları siler. PHP 8.1'den beri gelen birinci sınıf çağrılabilir (first-class callable) yazımı trim(...) aynı işi görür ve yazım hatasını çalışma anında değil, fonksiyon adı çözülürken yakalar. Bir sınıfın statik metodu için [Sinif::class, 'metot'] dizisi, nesne metodu için [$nesne, 'metot'] dizisi veya $nesne->metot(...) kullanılır.
Kılavuzdaki sürüm notlarına göre PHP 8.0'dan beri, array_map(), array_filter(), array_reduce() veya usort() gibi fonksiyonlara parametresini referansla (&$x) bekleyen bir callback verirseniz E_WARNING uyarısı alırsınız. Bu fonksiyonlar değerleri kopya olarak gönderir; callback içinde elemanı değiştirmeye çalışmak işe yaramaz. Diziyi yerinde değiştirmek istiyorsanız referanslı foreach veya array_walk() kullanın.
<?php
$girdi = [' elma ', 'ARMUT', ' kiraz'];
echo json_encode(array_map('trim', $girdi)), "
"; // çıktı: ["elma","ARMUT","kiraz"]
echo json_encode(array_map(trim(...), $girdi)), "
"; // çıktı: ["elma","ARMUT","kiraz"]
final class Metin
{
public static function kucuk(string $s): string
{
return mb_strtolower(trim($s));
}
}
echo json_encode(array_map([Metin::class, 'kucuk'], $girdi)), "
"; // çıktı: ["elma","armut","kiraz"]
$sayilar = array_map(intval(...), ['10', '7 adet', 'abc']);
echo json_encode($sayilar), "
"; // çıktı: [10,7,0]PHP 8.4: array_find(), array_find_key(), array_any(), array_all()

PHP 8.4 dört yeni dizi fonksiyonu ekledi. Dördü de önce diziyi, sonra callback'i alır ve callback'e değer ile anahtarı birlikte gönderir. Hepsi kısa devre yapar: sonucu belirleyen ilk elemanda durur, kalan elemanlar için callback çağrılmaz. Bu, array_filter() ile bütün diziyi süzüp ilk elemanı almaktan hem daha okunaklı hem de büyük dizilerde daha az iş demektir.
array_find(): callback'intruedöndürdüğü ilk elemanın değerini, bulamazsanulldöndürür.array_find_key(): aynı aramayı yapar ama değerin yerine anahtarı döndürür; bulamazsanull.array_any(): en az bir eleman koşulu sağlıyorsatrue.array_all(): bütün elemanlar koşulu sağlıyorsatrue; boş dizi için detruedöner, çünkü koşulu bozan bir eleman yoktur.
<?php
$stok = ['kalem' => 40, 'defter' => 0, 'silgi' => 15, 'cetvel' => 0];
var_dump(array_find($stok, fn($adet) => $adet === 0)); // çıktı: int(0)
var_dump(array_find_key($stok, fn($adet) => $adet === 0)); // çıktı: string(6) "defter"
var_dump(array_find_key($stok, fn($adet, $urun) => strlen($urun) > 10)); // çıktı: NULL
var_dump(array_any($stok, fn($adet) => $adet > 30)); // çıktı: bool(true)
var_dump(array_all($stok, fn($adet) => $adet > 0)); // çıktı: bool(false)
var_dump(array_all([], fn($adet) => $adet > 0)); // çıktı: bool(true)İlk örnekte array_find() sonucunun int(0) olduğuna dikkat edin: bulunan değer gerçekten 0'dır. Aranan değerin kendisi null olabiliyorsa "bulunamadı" ile "bulundu ama değeri null" durumlarını ayırmak için array_find_key() kullanıp anahtarın null olup olmadığına bakmak daha güvenlidir.
<?php
// PHP 8.5 veya üstü gerekir
$siradakiler = ['Ece', 'Mert', 'Sena'];
echo array_first($siradakiler), ' ', array_last($siradakiler), "\n"; // çıktı: Ece Sena
var_dump(array_first([])); // çıktı: NULLUygulamalı örnek: sipariş raporu
Şimdi bu fonksiyonları birlikte kullanarak küçük bir rapor hazırlayalım. Elimizde sipariş satırları var; ödenmiş siparişleri ayırıp toplam tutarı hesaplayacağız, müşteri adlarını tekil bir liste hâline getireceğiz ve 500 TL'yi aşan ilk siparişi bulacağız. Her adımın ayrı bir fonksiyonla yapıldığına ve hiçbir adımın asıl $siparisler dizisini değiştirmediğine dikkat edin.
<?php
$siparisler = [
['no' => 'S1', 'musteri' => 'Ece', 'tutar' => 320.0, 'odendi' => true],
['no' => 'S2', 'musteri' => 'Mert', 'tutar' => 750.5, 'odendi' => false],
['no' => 'S3', 'musteri' => 'Ece', 'tutar' => 610.0, 'odendi' => true],
['no' => 'S4', 'musteri' => 'Sena', 'tutar' => 95.0, 'odendi' => true],
];
$odenen = array_filter($siparisler, fn($s) => $s['odendi']);
$ciro = array_sum(array_column($odenen, 'tutar'));
$musteriler = array_values(array_unique(array_column($odenen, 'musteri')));
$buyuk = array_find($odenen, fn($s) => $s['tutar'] > 500);
echo count($odenen), " ödenmiş sipariş\n"; // çıktı: 3 ödenmiş sipariş
echo number_format($ciro, 2, ',', '.'), " TL\n"; // çıktı: 1.025,00 TL
echo implode(', ', $musteriler), "\n"; // çıktı: Ece, Sena
echo $buyuk['no'] ?? 'yok', "\n"; // çıktı: S3Aynı işi tek bir foreach döngüsüyle de yapabilirdiniz ve büyük veri kümelerinde tek geçiş daha az bellek harcar. Fonksiyonlu yazımın avantajı, her adımın ne yaptığının adından anlaşılmasıdır. Hangisini seçeceğiniz okunabilirlik ve veri boyutu arasındaki dengeye bağlıdır; çok büyük verilerde elemanları tek tek üreten generator yapısı da düşünülebilir. Tutarı biçimlendirmek için kullandığımız number_format() ise sprintf ve number_format yazısının konusu.
Sık yapılan hatalar
array_filter()sonrasında anahtarların sıralı olduğunu varsaymak: anahtarlar korunur;$sonuc[0]hiç var olmayabilir. Gerekirsearray_values()ekleyin.- Callback'siz
array_filter()ile'0'değerini kaybetmek: metin olarak sıfır da boş sayılır. Neyi atmak istediğinizi callback ile açıkça yazın. array_search()sonucunuifiçinde doğrudan kullanmak:0anahtarı yanlış sayılır.!== falseile test edin.in_array()ile katı olmayan arama: kullanıcıdan gelen metinleri sayılarla veya bool değerlerle karşılaştırırken üçüncü parametreyitrueyapın.array_map()callback'inde anahtar beklemek: callback yalnızca değerleri alır. Anahtar gerekiyorsaarray_keys()sonucunu ikinci dizi olarak verin veyaforeachkullanın.array_reduce()başlangıç değerini unutmak: boş dizide sonuçnullolur ve sonraki hesaplar beklenmedik sonuç verir.
Sık Sorulan Sorular
array_map() ile foreach arasında hız farkı var mı?
Kılavuz iki yöntem için genel bir hız karşılaştırması vermez. PHP 8.5 sürüm notlarında callback alan dizi fonksiyonlarının (array_find(), array_filter(), array_map(), usort() gibi) performansının iyileştirildiği yazıyor. Pratikte seçimi okunabilirliğe göre yapmak, darboğaz şüphesi varsa kendi kodunuzda ölçmek en doğrusudur.
Diziyi yerinde değiştiren bir map var mı?
array_walk() fonksiyonu callback'e elemanı referansla verebilir ve diziyi yerinde değiştirebilir. Bunun yerine foreach ($dizi as &$deger) yazımı da kullanılır; ancak döngüden sonra unset($deger) yapmayı unutmayın. Ayrıntılar PHP referanslar yazısında.
array_find() eski PHP sürümlerinde nasıl yazılır?
PHP 8.4 öncesinde aynı işi foreach içinde koşulu kontrol edip ilk eşleşmede return eden küçük bir fonksiyonla yapabilirsiniz. array_filter() ile süzüp ilk elemanı almak da çalışır, ama bütün diziyi dolaşır ve anahtarlar korunduğu için ilk elemanı reset() veya array_values() ile almanız gerekir.
Bir anahtarın dizide olup olmadığını nasıl anlarım?
Değer aramak için kullanılan in_array() anahtarlara bakmaz. Anahtar kontrolü için array_key_exists($anahtar, $dizi) veya isset($dizi[$anahtar]) kullanılır. İkisi arasındaki fark, değeri null olan anahtarlarda ortaya çıkar: isset() bu durumda false, array_key_exists() ise true döndürür. Bütün anahtarları bir liste olarak almak isterseniz array_keys() yeterlidir.
Tekrarlanan değerleri nasıl kaldırırım?
array_unique() tekrar eden değerleri atar ve ilk görülen elemanın anahtarını korur. Sonucu liste olarak kullanacaksanız uygulamalı örnekteki gibi array_values() ile yeniden numaralayın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: PHP öğrenme rehberi · PHP dizi temelleri · PHP dizi sıralama · anonim fonksiyon ve arrow function · PHP karşılaştırma ve tip dönüşümü · PHP 8.4 yenilikleri