PHP'de diziyi değerlerine göre küçükten büyüğe sıralamak için sort(), anahtarları koruyarak sıralamak için asort(), anahtarlara göre sıralamak için ksort(), kendi karşılaştırma kuralınızla sıralamak için usort() kullanılır. Bütün bu fonksiyonlar diziyi yerinde değiştirir ve sıralanmış yeni bir dizi döndürmez; dönüş değerleri her zaman true'dur.

Doğru fonksiyonu seçmek için üç soruya cevap vermeniz yeterli: değere mi anahtara mı göre sıralayacaksınız, anahtar ve değer arasındaki bağ korunmalı mı, sıralama yönü ne olacak? Bu yazıda kılavuzdaki sıralama tablosunu temel alarak bu soruları cevaplıyor, sıralama bayraklarını, <=> ile çok alanlı sıralamayı, PHP 8.0'dan beri geçerli olan kararlılık kuralını ve Türkçe kelimeleri doğru sıralamanın yolunu anlatıyoruz. Dizinin kendisi için PHP dizi temelleri yazısına bakabilirsiniz.

Sıralama fonksiyonları tablosu

Sıralama fonksiyonları tablosu: sort, rsort, asort, arsort

Kılavuzun "Sorting Arrays" sayfası fonksiyonları neye göre sıraladıkları, anahtarı koruyup korumadıkları ve sıralama düzenine göre bir tabloda toplar. Adlandırmada bir düzen var: başta a harfi (associative) anahtarın korunduğunu, k harfi anahtara göre sıralandığını, r harfi ters (azalan) sırayı, u harfi ise kullanıcı tanımlı karşılaştırma fonksiyonunu gösterir.

FonksiyonNeye göreAnahtar korunur muDüzen
sortdeğerhayırartan
rsortdeğerhayırazalan
asortdeğerevetartan
arsortdeğerevetazalan
ksortanahtarevetartan
krsortanahtarevetazalan
usortdeğerhayırkullanıcı tanımlı
uasortdeğerevetkullanıcı tanımlı
uksortanahtarevetkullanıcı tanımlı
natsortdeğerevetdoğal sıra
natcasesortdeğerevetdoğal sıra, harf duyarsız
shuffledeğerhayırrastgele
array_multisortdeğermetin anahtarlar evet, sayısal hayırilk dizi veya seçenekler

Yerinde sıralama: sort() ne döndürür?

Sıralama fonksiyonları diziyi referansla alır ve doğrudan onu değiştirir. Dönüş değeri sıralanmış dizi değil, her zaman true'dur; PHP 8.2'den beri dönüş tipi kılavuzda da true olarak yazılır. Bu yüzden $sirali = sort($dizi); yazmak en sık rastlanan hatalardan biridir: $sirali değişkeni true olur, sıralanan şey $dizi'nin kendisidir. sort(), rsort() ve usort() ayrıca var olan anahtarları siler ve elemanlara 0'dan başlayan yeni anahtarlar verir.

php
<?php
$sayilar = [5, 3, 10, 1];
$sonuc = sort($sayilar);

var_dump($sonuc);                 // çıktı: bool(true)
echo implode(', ', $sayilar), "\n"; // çıktı: 1, 3, 5, 10

$puan = ['Ece' => 85, 'Can' => 92, 'Ali' => 78];
sort($puan);
echo json_encode($puan), "\n";    // çıktı: [78,85,92]  (isimler kayboldu)

Asıl diziyi bozmadan sıralanmış bir kopya istiyorsanız, PHP'de dizilerin değer olarak kopyalandığını kullanabilirsiniz. Diziyi parametre olarak alan küçük bir fonksiyon, kendi kopyasını sıralayıp döndürür; çağıran taraftaki dizi değişmez.

php
<?php
function sirali(array $dizi): array
{
    sort($dizi);      // fonksiyonun kendi kopyası sıralanır
    return $dizi;
}

$asil = [3, 1, 2];
$kopya = sirali($asil);
echo implode(',', $asil), ' | ', implode(',', $kopya), "\n"; // çıktı: 3,1,2 | 1,2,3

Anahtarı koruyarak sıralamak: asort, arsort, ksort, krsort

İlişkisel dizilerde anahtar ile değer birlikte anlam taşır; öğrenci adı ile puanı gibi. Böyle bir diziyi sort() ile sıralarsanız isimler kaybolur. Değere göre sıralayıp eşleşmeyi korumak için asort() (artan) veya arsort() (azalan), anahtara göre sıralamak için ksort() veya krsort() kullanılır.

php
<?php
$puan = ['Ece' => 85, 'Can' => 92, 'Ali' => 78];

$a = $puan; asort($a);  echo json_encode($a), "\n"; // çıktı: {"Ali":78,"Ece":85,"Can":92}
$a = $puan; arsort($a); echo json_encode($a), "\n"; // çıktı: {"Can":92,"Ece":85,"Ali":78}
$a = $puan; ksort($a);  echo json_encode($a), "\n"; // çıktı: {"Ali":78,"Can":92,"Ece":85}
$a = $puan; krsort($a); echo json_encode($a), "\n"; // çıktı: {"Ece":85,"Can":92,"Ali":78}

ksort() için kılavuzda bir sürüm notu var: PHP 8.2'den beri SORT_REGULAR kipinde sayısal metin anahtarlar PHP 8'in standart karşılaştırma kurallarıyla karşılaştırılıyor. Hem sayısal hem metin anahtar içeren dizileri eski sürümlerden taşıyorsanız sıralama sonucunu yeniden kontrol edin.

Sıralama bayrakları: SORT_STRING, SORT_NUMERIC, SORT_NATURAL

Sıralama bayrakları: SORT_STRING, SORT_NUMERIC, SORT_NATURAL

sort(), rsort(), asort(), ksort() ve benzerleri ikinci parametre olarak bir bayrak alır. Varsayılan SORT_REGULAR, değerleri PHP'nin normal karşılaştırma kurallarıyla karşılaştırır; bu kurallara göre iki sayısal metin sayı gibi karşılaştırılır. SORT_STRING her şeyi metin olarak, SORT_NUMERIC her şeyi sayı olarak karşılaştırır. SORT_NATURAL, insanların beklediği "doğal sıra"yı uygular: dosya2, dosya10'dan önce gelir. SORT_FLAG_CASE bayrağı SORT_STRING veya SORT_NATURAL ile | operatörüyle birleştirilerek büyük/küçük harf ayrımını kaldırır.

php
<?php
$kodlar = ['10', '9', '2', '1'];
$a = $kodlar; sort($a);              echo implode(' ', $a), "\n"; // çıktı: 1 2 9 10
$a = $kodlar; sort($a, SORT_STRING); echo implode(' ', $a), "\n"; // çıktı: 1 10 2 9

$dosyalar = ['img12.png', 'img10.png', 'IMG2.png', 'img1.png'];
$a = $dosyalar; sort($a);
echo implode(' ', $a), "\n";  // çıktı: IMG2.png img1.png img10.png img12.png
$a = $dosyalar; sort($a, SORT_NATURAL);
echo implode(' ', $a), "\n";  // çıktı: IMG2.png img1.png img10.png img12.png
$a = $dosyalar; sort($a, SORT_NATURAL | SORT_FLAG_CASE);
echo implode(' ', $a), "\n";  // çıktı: img1.png IMG2.png img10.png img12.png

Dosya listesindeki ilk iki sonucun aynı çıkması tesadüf değil: büyük harfler bayt değeri olarak küçük harflerden önce geldiği için IMG2.png hem normal hem doğal sıralamada başa geçer. Harf duyarsız doğal sıra ancak SORT_FLAG_CASE eklendiğinde istenen sonucu verir. Aynı işi anahtarları koruyarak yapan kısa fonksiyonlar natsort() ve natcasesort()'tur.

usort() ve uzay gemisi operatörü ile özel sıralama

usort(), iki elemanı alıp bir tam sayı döndüren bir karşılaştırma fonksiyonu ister: birinci eleman küçükse sıfırdan küçük, eşitse sıfır, büyükse sıfırdan büyük bir değer. Bu sözleşmeyi en kısa yoldan sağlayan araç uzay gemisi operatörü <=>'dir; $a <=> $b tam olarak -1, 0 veya 1 döndürür. Azalan sıra için iki tarafın yerini değiştirmeniz yeter: $b <=> $a.

Çok alanlı sıralama için iki diziyi <=> ile karşılaştırma kuralından yararlanabilirsiniz. Kılavuzdaki karşılaştırma tablosuna göre aynı uzunluktaki iki dizi değer değer karşılaştırılır; ilk farklı eleman sonucu belirler. Böylece "önce kategoriye göre artan, aynı kategoride fiyata göre azalan" gibi bir kuralı tek satırda yazabilirsiniz: azalan olması gereken alanda $a ile $b'nin yerini değiştirmeniz yeterlidir.

php
<?php
$urunler = [
    ['ad' => 'Defter', 'kat' => 'kırtasiye', 'fiyat' => 30],
    ['ad' => 'Kulaklık', 'kat' => 'elektronik', 'fiyat' => 450],
    ['ad' => 'Kalem', 'kat' => 'kırtasiye', 'fiyat' => 12],
    ['ad' => 'Mouse', 'kat' => 'elektronik', 'fiyat' => 300],
    ['ad' => 'Silgi', 'kat' => 'kırtasiye', 'fiyat' => 30],
];

usort($urunler, fn($a, $b) => [$a['kat'], $b['fiyat']] <=> [$b['kat'], $a['fiyat']]);

foreach ($urunler as $u) {
    echo "{$u['kat']}  {$u['fiyat']}  {$u['ad']}\n";
}
/* çıktı:
elektronik  450  Kulaklık
elektronik  300  Mouse
kırtasiye  30  Defter
kırtasiye  30  Silgi
kırtasiye  12  Kalem
*/

Çıktıda Defter ve Silgi'nin kategorisi ve fiyatı aynı. Bu iki ürün, karşılaştırma fonksiyonu açısından eşittir ve sonuçta orijinal dizideki sıralarını korudular. Bu davranışın adı kararlı sıralamadır ve bir sonraki bölümün konusu.

Kararlılık: eşit elemanlar yerini korur

Kılavuza göre PHP 8.0'dan beri bütün sıralama fonksiyonları kararlıdır: iki eleman eşit sayılırsa orijinal sıralarını korurlar. PHP 8.0'dan önce eşit elemanların sırası tanımsızdı. Bu garanti, aşamalı sıralama yapmanıza izin verir: önce ikincil ölçüte göre, sonra birincil ölçüte göre sıralarsanız, birincil ölçütte eşit olanlar ikincil sırayı korur. Yine de tek bir usort() içinde bütün ölçütleri yazmak, niyetinizi daha açık gösterir.

Kararlılıkla ilgili ince bir tuzak, karşılaştırma fonksiyonunun dönüş değerinde saklıdır. Kılavuz, karşılaştırma fonksiyonundan tam sayı olmayan bir değer döndürmenin içeride int'e çevrildiğini belirtir. Ondalık sayıları $a - $b ile karşılaştırırsanız 0.3 gibi farklar 0'a yuvarlanır, elemanlar eşit sayılır ve kararlı sıralama onları hiç yer değiştirmeden bırakır. Sonuç, hiçbir uyarı olmadan sıralanmamış bir dizidir.

php
<?php
$oranlar = [0.5, 0.2, 0.9, 0.1];

$a = $oranlar;
usort($a, fn($x, $y) => $x - $y);       // YANLIŞ: fark int'e çevrilir
echo implode(' ', $a), "\n";            // çıktı: 0.5 0.2 0.9 0.1

$a = $oranlar;
usort($a, fn($x, $y) => $x <=> $y);     // DOĞRU
echo implode(' ', $a), "\n";            // çıktı: 0.1 0.2 0.5 0.9

uasort() ve uksort(): kullanıcı tanımlı, anahtar korunarak

uasort(), usort() gibi çalışır ama anahtarları korur; ilişkisel bir diziyi değere göre özel bir kuralla sıralamak için kullanılır. uksort() ise karşılaştırma fonksiyonuna değerleri değil anahtarları verir. Aşağıda şehir adlarını önce uzunluklarına, aynı uzunluktakileri alfabeye göre sıralıyoruz. Uzunluk için mb_strlen() kullandık; çünkü strlen() bayt sayar ve Türkçe karakterli adlarda yanlış sonuç verir. Bu farkın ayrıntısı PHP mbstring ve Türkçe karakterler yazısında.

php
<?php
$sepet = ['kalem' => ['adet' => 4], 'defter' => ['adet' => 10], 'silgi' => ['adet' => 1]];
uasort($sepet, fn($a, $b) => $b['adet'] <=> $a['adet']);
echo implode(', ', array_keys($sepet)), "\n";   // çıktı: defter, kalem, silgi

$plaka = ['İzmir' => 35, 'Muş' => 49, 'Ankara' => 6, 'Çorum' => 19];
uksort($plaka, fn($a, $b) => [mb_strlen($a), $a] <=> [mb_strlen($b), $b]);
echo implode(', ', array_keys($plaka)), "\n";   // çıktı: Muş, Çorum, İzmir, Ankara

Son satırda Çorum'un İzmir'den önce gelmesi dikkatinizi çekmiş olabilir. İki ad da beş karakterlik olduğu için ikinci ölçüt devreye girer ve metinler bayt değerine göre karşılaştırılır. UTF-8'de Ç harfinin ilk baytı İ harfininkinden küçük olduğu için sonuç alfabetik görünür; ama bu bir rastlantıdır. Türkçe alfabe sırasına güvenmek için bayt karşılaştırması yeterli değildir.

Türkçe kelimeleri doğru sıralamak: Collator

sort() metinleri bayt değerlerine göre karşılaştırır. Türkçe harfler (ç, ğ, ı, ö, ş, ü ve büyük İ) UTF-8'de birden fazla baytla yazılır ve bayt değerleri İngilizce harflerin hepsinden büyüktür. Sonuç olarak çay, zeytin'den sonra gelir ve büyük harfle başlayan kelimeler küçük harflilerden önce sıralanır. SORT_LOCALE_STRING bayrağı setlocale() ile ayarlanan yerel ayara bakar; ancak hangi yerel ayarların kullanılabildiği işletim sistemine bağlıdır.

Daha taşınabilir çözüm, intl eklentisindeki Collator sınıfıdır. new Collator('tr_TR') ile Türkçe harmanlama kurallarını yükler, sort() metoduyla diziyi bu kurallara göre sıralarsınız. Anahtarları korumak için asort() metodu vardır. Kılavuz, bu metotları standart sort() ve asort() fonksiyonlarının yerel ayara duyarlı karşılığı olarak tanımlar. Bu yolun tek şartı intl eklentisinin sunucuda yüklü olmasıdır.

php
<?php
$kelimeler = ['şeker', 'çay', 'zeytin', 'ılık', 'inci', 'Ağaç', 'cam', 'ödev', 'ot'];

$a = $kelimeler;
sort($a);
echo implode(', ', $a), "\n";
// çıktı: Ağaç, cam, inci, ot, zeytin, çay, ödev, ılık, şeker

$a = $kelimeler;
$tr = new Collator('tr_TR');
$tr->sort($a);
echo implode(', ', $a), "\n";
// çıktı: Ağaç, cam, çay, ılık, inci, ot, ödev, şeker, zeytin

$sehirler = ['s3' => 'Şanlıurfa', 's1' => 'Çanakkale', 's2' => 'Sinop'];
$tr->asort($sehirler);
echo json_encode($sehirler, JSON_UNESCAPED_UNICODE), "\n";
// çıktı: {"s1":"Çanakkale","s2":"Sinop","s3":"Şanlıurfa"}

Türkçe kurallarda ı harfinin i'den önce, ö'nün o'dan sonra geldiğine ve büyük harfle başlayan Ağaç'ın alfabedeki doğru yerine oturduğuna dikkat edin. usort() içinde de $tr->compare($a, $b) çağırarak aynı kuralları çok alanlı sıralamalarda kullanabilirsiniz.

Hangi sıralama fonksiyonunu seçmeliyim?

Hangi sıralama fonksiyonunu seçmeliyim? Sade bir sayı veya metin listesi, anahtarlar önemsiz, Anahtar ile değer birlikte anlamlı (ad ve puan gibi), değere göre sıralama..., Ayar...

Aşağıdaki kısa karar listesi, günlük işlerin büyük kısmında doğru fonksiyona hızlıca ulaşmanızı sağlar. Hepsinde ortak kural aynıdır: fonksiyon diziyi yerinde değiştirir, asıl diziyi korumak istiyorsanız önce bir kopya alın.

  • Sade bir sayı veya metin listesi, anahtarlar önemsiz: sort() veya rsort().
  • Anahtar ile değer birlikte anlamlı (ad ve puan gibi), değere göre sıralama: asort() veya arsort().
  • Ayar veya sözlük dizisini anahtar adına göre düzenlemek: ksort() veya krsort().
  • Satır listesi (veritabanı sonucu gibi) bir veya birkaç alana göre: usort() ve uzay gemisi operatörü; anahtar korunacaksa uasort().
  • Dosya adı, sürüm numarası gibi sayı içeren metinler: SORT_NATURAL bayrağı veya natsort(); harf duyarsız için SORT_FLAG_CASE ya da natcasesort().
  • Türkçe veya başka bir dilin alfabe kuralları: intl eklentisindeki Collator; çok alanlı sıralamada usort() içinde compare() metodu.

Son maddedeki birleşim, gerçek projelerde sık gerekir: örneğin müşteri listesini önce şehre, sonra soyada göre Türkçe kurallarla sıralamak. Collator::compare() iki metni karşılaştırıp -1, 0 veya 1 döndürdüğü için doğrudan karşılaştırma fonksiyonu olarak kullanılabilir. İkinci ölçüte yalnızca birinci ölçüt eşit çıktığında geçmek için ?: operatörünü kullanıyoruz; sol taraf 0 ise sağ taraf hesaplanır.

php
<?php
$tr = new Collator('tr_TR');
$musteriler = [
    ['sehir' => 'İzmir',  'soyad' => 'Şahin'],
    ['sehir' => 'Çorum',  'soyad' => 'Yıldız'],
    ['sehir' => 'İzmir',  'soyad' => 'Çelik'],
    ['sehir' => 'Ankara', 'soyad' => 'Öztürk'],
];
usort($musteriler, fn($a, $b) =>
    $tr->compare($a['sehir'], $b['sehir']) ?: $tr->compare($a['soyad'], $b['soyad']));

foreach ($musteriler as $m) {
    echo $m['sehir'], ' ', $m['soyad'], "
";
}
/* çıktı:
Ankara Öztürk
Çorum Yıldız
İzmir Çelik
İzmir Şahin
*/

Sık yapılan hatalar

  • Dönüş değerini sıralı dizi sanmak: $x = sort($d) yazımında $x yalnızca true olur.
  • İlişkisel diziyi sort() ile sıralamak: anahtarlar silinir. Değere göre sıralayıp anahtarı korumak için asort() veya uasort() kullanın.
  • Karşılaştırma fonksiyonundan ondalık fark döndürmek: sonuç int'e çevrilir; ondalıklarda her zaman <=> kullanın.
  • Karşılaştırma fonksiyonundan bool döndürmek: fn($a, $b) => $a > $b yalnızca 0 veya 1 üretir ve "küçüktür" durumunu hiç bildirmez; sözleşmeye uygun olarak negatif, sıfır veya pozitif bir tam sayı döndürün.
  • Türkçe metinleri sort() ile sıralamak: bayt sırası alfabe sırası değildir; Collator kullanın.
  • Sayısal metinleri yanlış bayrakla sıralamak: ürün kodu gibi metin olarak kalması gereken değerlerde SORT_STRING, sayı olarak sıralanması gerekenlerde SORT_NUMERIC verin.

Sık Sorulan Sorular

Sıralama fonksiyonları hangi algoritmayı kullanır?

Kılavuz, PHP sıralama fonksiyonlarının çoğunun Quicksort tabanlı bir uygulama kullandığını, ancak bunun güvenmemeniz gereken bir uygulama ayrıntısı olduğunu söyler. Güvenebileceğiniz garanti, PHP 8.0'dan beri sıralamanın kararlı olmasıdır.

Diziyi tersine çevirmek ile azalan sıralamak aynı şey mi?

Hayır. array_reverse() yalnızca mevcut sırayı tersine çevirir, değerlere bakmaz. Azalan sıralama için rsort(), arsort() veya karşılaştırmada taraf değiştirilmiş bir usort() kullanın.

Diziyi rastgele karıştırmak için ne kullanırım?

shuffle() diziyi yerinde karıştırır ve anahtarları sıfırdan yeniden verir. Tek bir rastgele anahtar seçmek için array_rand() vardır. Şifre veya jeton gibi güvenlik gerektiren değerler için bu fonksiyonlar yerine random_bytes ve password_hash yazısındaki araçlara bakın.

Satır listesini bir sütuna göre sıralamanın başka yolu var mı?

array_multisort() birden fazla diziyi aynı anda sıralayabilir. Kılavuzdaki veritabanı örneğinde önce array_column() ile sıralama ölçütü olan sütunlar ayrı dizilere çekilir, sonra bu diziler ve asıl veri array_multisort()'a verilir; asıl veri ölçüt dizileriyle aynı sıraya dizilir. Bu yöntem çalışır ama okunması usort() kadar kolay değildir; ayrıca sayısal anahtarları yeniden numaralar.

Nesne dizisini bir özelliğe göre nasıl sıralarım?

usort() ile aynı şekilde: usort($liste, fn($a, $b) => $a->ad <=> $b->ad). Nesneler referans gibi davrandığı için karşılaştırma sırasında kopyalanmazlar; sınıf yapısı için PHP sınıf ve nesne yazısına bakabilirsiniz.

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 fonksiyonları · PHP operatörler ve öncelik · PHP mbstring ve Türkçe karakterler