Arrays7 min readExamples run on PHP 8.5.10

natcasesort()

Learn how natcasesort() sorts arrays in case-insensitive natural order, keeps keys, returns true, and where it differs from natsort() and sort().

Signature

natcasesort(array &$array): true

Purpose

natcasesort() sorts an array in place using a case-insensitive "natural order" comparison. Natural order treats runs of digits as numbers, so img2 comes before img10, the way a person would expect. Ordinary string sorting compares character by character and puts img10 first, because 1 is smaller than 2.

The function keeps the association between keys and values. It is the case-insensitive sibling of natsort(). Typical uses are file names, version-like labels, product codes and any list where numbers are embedded in text.

Signature

Parameters and defaults

  • $array: the array to sort. It is passed by reference and modified in place. There are no other parameters and no default values.

Because the argument is a reference, you must pass a variable. A literal such as natcasesort(['a', 'b']) is not valid, because PHP has nothing to write the result back to.

Return value and failure cases

The function always returns true. Since PHP 8.2 the declared return type is true; earlier versions declared bool. The return value carries no information, so there is no point in testing it with if. The real result is the changed array.

Two behaviors to remember:

  • Elements that compare as equal keep their original relative order. This is guaranteed since PHP 8.0.0; before that the order was undefined.
  • The array's internal pointer is reset to the first element.

Example 1: file names with mixed case

The array below mixes upper and lower case and has numbers of different lengths. After sorting, the values are in natural order, but each one keeps its old key. The JSON therefore comes out as an object with the original numeric keys.

Example
<?php
$files = ['IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png'];
natcasesort($files);
echo json_encode($files, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":"IMG0.png","4":"img1.png","3":"img2.png","5":"IMG3.png","2":"img10.png","1":"img12.png"}

Example 2: return value and re-indexing

Keys survive sorting, so the array is no longer a list in key order. If the next code needs sequential keys, call array_values() on the result.

Example
<?php
$items = ['Item 10', 'item 9', 'ITEM 2'];
$result = natcasesort($items);
echo json_encode($result), "\n";
echo json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(array_values($items), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
true
{"2":"ITEM 2","1":"item 9","0":"Item 10"}
["ITEM 2","item 9","Item 10"]

Example 3: ties and the difference from natsort()

Here b1 and B1 are equal when case is ignored, so natcasesort() leaves them in their original order. natsort() is case-sensitive, so uppercase B1 sorts ahead of lowercase letters.

Example
<?php
$names = ['b1', 'B1', 'a1'];
$ignoreCase = $names;
$caseSensitive = $names;
natcasesort($ignoreCase);
natsort($caseSensitive);
echo json_encode($ignoreCase, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode($caseSensitive, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"2":"a1","0":"b1","1":"B1"}
{"1":"B1","2":"a1","0":"b1"}

Edge cases

  • Empty or one-element arrays are left as they are, and the function still returns true.
  • Equal elements under case folding keep their input order, as Example 3 shows.
  • String keys are preserved just like numeric keys. Only the order of the entries changes.
  • Designed for strings. The algorithm is meant for alphanumeric text. If your data is numeric or has a custom ordering, check the result with a small test or use a function intended for that data.
  • Internal pointer. After the call, current() points at the first element of the sorted array.

Common mistakes

  1. Expecting a sorted copy. natcasesort() returns true, not the array. Writing $sorted = natcasesort($list); gives you true in $sorted.
  2. Forgetting that keys are kept. A foreach loop visits entries in the sorted order, but $array[0] is still whatever had key 0 before sorting. Use array_values() when you need a fresh list.
  3. Using natsort() for user-facing, case-insensitive lists. Uppercase names will cluster before lowercase ones.
  4. Using sort() for numbered labels. Plain sorting puts img10.png before img2.png.
  5. Passing a non-variable. Function results and literals cannot be passed by reference, so assign the array to a variable first.
  6. Relying on this for locale-aware ordering. The function offers natural ordering with case ignored. It is not a replacement for language-specific collation.
  • natsort(): the same natural-order algorithm, but case-sensitive.
  • strnatcmp() and strnatcasecmp(): compare two strings in natural order, useful inside uasort() or usort() callbacks.
  • sort(), asort() and ksort(): standard comparisons, with asort() also preserving keys.
  • array_values(): re-indexes an array after a key-preserving sort.

Recap

natcasesort(array &$array): true reorders an array in place so that embedded numbers sort by value and letter case is ignored. Keys stay attached to their values, equal elements keep their original order, and the return value is always true. Reach for array_values() when you need sequential keys, and for natsort() when case should matter.

Tested examples

Sorting file names with mixed case
<?php
$files = ['IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png'];
natcasesort($files);
echo json_encode($files, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"0":"IMG0.png","4":"img1.png","3":"img2.png","5":"IMG3.png","2":"img10.png","1":"img12.png"}
Return value and re-indexing
<?php
$items = ['Item 10', 'item 9', 'ITEM 2'];
$result = natcasesort($items);
echo json_encode($result), "\n";
echo json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(array_values($items), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
true
{"2":"ITEM 2","1":"item 9","0":"Item 10"}
["ITEM 2","item 9","Item 10"]
Ties and the difference from natsort()
<?php
$names = ['b1', 'B1', 'a1'];
$ignoreCase = $names;
$caseSensitive = $names;
natcasesort($ignoreCase);
natsort($caseSensitive);
echo json_encode($ignoreCase, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode($caseSensitive, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"2":"a1","0":"b1","1":"B1"}
{"1":"B1","2":"a1","0":"b1"}