Aikido

PHP'de neden array_filter() fonksiyonunu array_values() ile sarmalamalısınız

Hata Riski

Kural
Dizi filtreleme sonuçlarını array_values() ile sarmalayın
array_filter() gibi fonksiyonlar orijinal anahtarları korur;
bu da kod 0'dan başlayan sıralı
sayısal indeksler beklediğinde hatalara yol açabilir.

Desteklenen diller: PHP

Giriş

PHP'nin array_filter() elemanları filtrelerken, sayısal olarak indekslenmiş dizilerde bile orijinal dizi anahtarlarını korur. Filtreleme sonrasında [0 => 'a', 1 => 'b', 2 => 'c'] 1. indeksi kaldırdığınızda, elinizde [0 => 'a', 2 => 'c'] sayısal anahtarlarında boşluk bulunan bir yapı kalır. 0'dan başlayan ardışık indeksler bekleyen kodlar, bunlara erişmeye çalışırken veya $array[1] kesintisiz indeks varsayımlarıyla döngü çalıştırırken hata verir. Bu davranış, filtrelemenin yeniden indekslenmiş diziler döndürdüğü diğer dillerden gelen geliştiricileri şaşırtır.

Neden önemli?

Kod sürdürülebilirliği: Ardışık olmayan dizi anahtarları, yalnızca belirli koşullarda ortaya çıkan sinsi hatalara yol açar. Filtrelenmemiş dizilerle sorunsuz çalışan kod, filtreleme sonrasında count($array) - 1 ifadesinin en yüksek geçerli indeks olduğunu varsaydığı için gizemli bir şekilde başarısız olur. Bu tür sorunları ayıklamak zaman kaybettirir çünkü kök neden hemen belli olmaz; üç elemanlı bir dizi görürsünüz ancak 1 indeksli ikinci elemana erişemezsiniz.

JSON kodlama sorunları: Şu fonksiyonu kullandığınızda json_encode() ardışık olmayan anahtarlara sahip bir dizi için PHP bunu bir dizi yerine nesne olarak ele alır ve {"0":"a","2":"c"} sonucunu üretir ["a","c"]yerine. JSON dizileri bekleyen arayüz (frontend) kodları nesneler alır; bu da döngülerin ve dizi metotlarının çalışmasını engeller. PHP dizileri ile JavaScript dizileri arasındaki bu uyumsuzluk, yalnızca filtreleme işlemlerinden sonra ortaya çıkan entegrasyon hatalarına neden olur.

Döngü ve sayfalama (pagination) hataları: Sonuçları sayfalayan veya dizileri parçalara ayıran kodlar, anahtarlar ardışık olmadığında hata verir. 0'dan count($array) değerine kadar döngü kurmak, tanımlanmamış indekslere erişmeye çalışır. Sayfalama için array_slice() kullanmak, konumlar üzerinden işlem yapıp orijinal anahtarları döndürdüğü için beklenmeyen sonuçlar doğurur. Bu hatalar, karmaşık veri işleme hatlarında katlanarak artar.

Kod örnekleri

❌ Kural dışı:

function getActiveUsers(array $users): array {
    $activeUsers = array_filter($users, function($user) {
        return $user['status'] === 'active';
    });

    // Bug: assumes index 0 exists and keys are sequential
    $firstActive = $activeUsers[0] ?? null;

    // Bug: JSON encodes as object if keys aren't sequential
    return json_encode($activeUsers);
}

$users = [
    ['id' => 1, 'status' => 'inactive'],
    ['id' => 2, 'status' => 'active'],
    ['id' => 3, 'status' => 'active']
];

// Returns {"1":{"id":2...},"2":{"id":3...}} (object, not array)
getActiveUsers($users);

Neden yanlış: Filtreleme işlemi 0 indeksini kaldırdıktan sonra, dizide şu anahtarlar kalır: [1, 2] sonucunu üretir [0, 1]ve bu durum $activeUsers[0] değerinin undefined olmasına yol açar. Anahtarlar ardışık olmadığı için JSON kodlaması dizi yerine bir nesne (object) üretir ve bu da dizi bekleyen frontend kodunu bozar.

✅ Kurallara uygun:

function getActiveUsers(array $users): string {
    $activeUsers = array_filter($users, function($user) {
        return $user['status'] === 'active';
    });

    // Reindex to sequential keys starting from 0
    $activeUsers = array_values($activeUsers);

    // Now index 0 always exists for non-empty arrays
    $firstActive = $activeUsers[0] ?? null;

    // JSON encodes as proper array: [{"id":2...},{"id":3...}]
    return json_encode($activeUsers);
}

$users = [
    ['id' => 1, 'status' => 'inactive'],
    ['id' => 2, 'status' => 'active'],
    ['id' => 3, 'status' => 'active']
];

// Returns [{"id":2...},{"id":3...}] (array, as expected)
getActiveUsers($users);

Neden önemli: array_values() fonksiyonu, filtrelenen diziyi 0'dan başlayan ardışık sayısal anahtarlarla yeniden indeksler; böylece indeks erişimi öngörülebilir hale gelir ve JSON kodlamasının nesne yerine dizi üretmesi sağlanır. Bu fonksiyon, hangi öğelerin filtrelendiğinden bağımsız olarak beklendiği gibi çalışır.

Sonuç

Ardışık sayısal indekslere ihtiyaç duyduğunuzda array_filter(), array_diff()fonksiyonunu ve benzer diğer fonksiyonları her zaman array_values() ile sarmalayın. Bu, ardışık olmayan anahtarlardan kaynaklanan zor fark edilir hataları önler ve JSON kodlamasının nesne yerine dizi üretmesini sağlar. Performans maliyeti, kazanılan hata ayıklama süresinin yanında göz ardı edilebilecek kadar azdır.

Sık Sorulan Sorular

Sorularınız mı var?

Hangi PHP dizi fonksiyonları anahtarları korur ve array_values() gerektirir?

array_filter(), array_diff(), array_diff_key(), array_intersect() ve array_intersect_key() fonksiyonlarının tümü orijinal anahtarları korur. Tek bir dizi parametresi alan array_map() gibi fonksiyonlar da anahtarları korur. Anahtarları koruduğu belirtilen herhangi bir fonksiyon, ardışık indekslere ihtiyacınız varsa array_values() ile sarmalanmalıdır.

array_values() fonksiyonunun performans üzerinde bir etkisi var mı?

Minimum düzeyde. array_values() fonksiyonu, diziyi yeniden indekslemek için üzerinde bir kez döngü çalıştırır; bu O(n) karmaşıklığındadır ancak pratikte oldukça hızlıdır. Bu maliyet, filtreleme işleminin kendisinin yanında ihmal edilebilir düzeydedir ve ardışık olmayan anahtarlardan kaynaklanan prodüksiyon sorunlarını ayıklamaktan çok daha azdır. Her zaman erken optimizasyondan ziyade doğruluğa öncelik verin.

Metin tabanlı anahtarlara sahip ilişkisel diziler (associative arrays) hakkında ne söyleyebiliriz?

Anahtarların anlamlı metinler olduğu ilişkisel dizilerde array_values() kullanmayın. Bu işlem, metin tabanlı anahtarlarınızı sayısal indekslerle değiştirerek önemli bilgileri kaybetmenize neden olur. Bu kural yalnızca 0'dan başlayan ardışık anahtarların beklendiği sayısal indeksli diziler için geçerlidir.

Bunun yerine array_splice() veya başka fonksiyonlar kullanabilir miyim?

array_splice() otomatik olarak yeniden indeksleme yapar ancak bu fonksiyon filtreleme için değil, ekleme ve çıkarma işlemleri için tasarlanmıştır. Filtreleme işlemleri için array_filter() fonksiyonunu array_values() ile birlikte kullanmak daha anlaşılır ve daha tabiata uygundur. Yeniden indekslemeyi yan etki olarak elde etmek için fonksiyonları kötüye kullanmak yerine iş için doğruacı aracı kullanın.

Kod tabanımda bu sorunu nasıl test edebilirim?

Sonuçlarına sayısal indeksle erişilen, JSON olarak kodlanan veya ardışık anahtar bekleyen fonksiyonlara iletilen array_filter() çağrılarını arayın. Filtrelenen öğelerin dizinin sonunda yer almadığı verilerle test edin. İlk veya orta öğelerin kaldırılması hatalara yol açıyorsa, array_values() kullanmanız gerekir.

Şimdi güvenliğinizi sağlayın

Kodunuzu, bulutunuzu ve çalışma zamanınızı tek bir merkezi sistemde güvenceye alın.
Güvenlik açıklarını otomatik olarak hızla bulun ve düzeltin.

Kredi kartı gerekmez | Tarama sonuçları 32 saniyede.