strnatcmp
Compares two strings in human "natural" order, treating digit runs as numbers.
strnatcmp(string $string1, string $string2): int- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string1 | string | The first string. |
$string2 | string | The second string. |
Return value
intA value less than 0 if string1 is less than string2, a value greater than 0 if string1 is greater than string2, and 0 if they are equal.
Changelog
- PHP 8.2.0This function is no longer guaranteed to return strlen($string1) - strlen($string2) when string lengths are not equal, but may now return -1 or 1 instead.
strnatcmp() implements Martin Pool's "natural order" algorithm. It walks both strings together, comparing letters normally but comparing consecutive digits as a single number. That is why img2.png comes before img10.png, which a plain strcmp() gets backwards.
When to reach for it
Use it any time a list is going to be read by a person and the labels contain numbers: filenames, invoice references, exam question numbers, page names. Pass it to usort() as the comparison callback, or use natsort() if the keys must survive.
What trips people up
It is case sensitive, and uppercase letters sort before lowercase ones. strnatcmp('Item 10', 'item 9') is negative purely because I is byte 73 and i is byte 105 — the numbers never get compared. Use strnatcasecmp() when the case of your data is not under your control.
Treat the return value as a sign only. Since PHP 8.2 it usually returns -1, 0 or 1 rather than a difference, so any arithmetic on the result is unsafe.
Leading zeros are compared as fractional parts, so x007 ranks below x7 rather than equal to it.
Example
When to use it
- Sort screenshot files img1.png, img2.png, img10.png into the order a person expects.
- Order invoice or purchase-order references such as PO-9 and PO-100.
- Sort simple dotted numbers like 1.2.10 and 1.9.0 where full version_compare semantics are not needed.
Frequently asked questions
What is the difference between strcmp and strnatcmp?
strcmp compares byte by byte, so "img10" sorts before "img2". strnatcmp compares each run of digits as a number, producing the order a human reader expects.
Is strnatcmp case sensitive?
Yes. Uppercase letters sort before lowercase ones, and the case difference is decided before any digits are compared. Use strnatcasecmp() for a case-insensitive comparison.
How do I sort an array in natural order in PHP?
Call usort($array, 'strnatcmp') for a reindexed list, or natsort($array) to sort in place while preserving the keys.
More examples
Case sensitivity bites first
The first call is negative even though 10 is larger than 9, because the uppercase I is compared before the digits are ever reached. The case-insensitive version gets it right. The sorted array shows the same effect: ITEM 2 and Item 10 group ahead of item 9 by case, not by number.
<?php
var_dump(strnatcmp('Item 10', 'item 9')); // int(-1)
var_dump(strnatcasecmp('Item 10', 'item 9')); // int(1)
$mixed = ['Item 10', 'item 9', 'ITEM 2'];
usort($mixed, 'strnatcmp');
print_r($mixed);Sorting dotted numbers
Both calls produce 1.2.10, 1.9.0, 1.10.0 because each dotted segment is a clean digit run. They diverge as soon as a suffix like 1.10.0-beta appears, which version_compare ranks below 1.10.0 while strnatcmp ranks it above.
<?php
$versions = ['1.10.0', '1.9.0', '1.2.10'];
usort($versions, 'strnatcmp');
print_r($versions);
usort($versions, 'version_compare');
print_r($versions);
Discussion