Signature
strncasecmp(string $string1, string $string2, int $length): intPurpose
strncasecmp() compares only the beginning of two strings, ignoring letter case. You choose how many characters take part in the comparison. It is a good fit for prefix checks such as command names, protocol labels or code prefixes, where the rest of the string does not matter.
It is the length-limited sibling of strcasecmp(). The function is binary safe, meaning it works on raw bytes and does not stop at special characters.
Signature
Parameters
$string1: the first string.$string2: the second string.$length: the maximum number of characters from each string to compare. It is an upper limit. If a string is shorter than$length, the whole string is used.
None of the parameters has a default value, so all three must be passed.
Return value and failure cases
The function returns an int:
- a value less than
0if$string1is less than$string2, - a value greater than
0if$string1is greater than$string2, 0if the compared parts are equal.
Only the sign of the result is meaningful. Since PHP 8.2.0 the function is no longer guaranteed to return the difference of the string lengths when they differ. It may return -1 or 1 instead. Never rely on the exact magnitude.
A negative $length is invalid and throws a ValueError in PHP 8. Passing 0 is allowed and always yields 0, because nothing is compared.
Example 1: a reusable prefix check
Wrapping the call in a small helper makes the intent clear. The helper passes the prefix length as $length.
function startsWithIgnoreCase(string $text, string $prefix): bool
{
return strncasecmp($text, $prefix, strlen($prefix)) === 0;
}
var_dump(startsWithIgnoreCase('Help me', 'help'));
var_dump(startsWithIgnoreCase('Hello John', 'hello Doe'));
var_dump(strncasecmp('Hello John', 'hello Doe', 5));bool(true) bool(false) int(0)
The first call matches despite the different case. The second compares nine characters and finds J against D. The last call limits the comparison to five characters, so only Hello against hello is checked and the result is 0.
Example 2: reading the sign
Because the exact number is not reliable, normalize it with the spaceship operator when you want a stable value.
$result = [
'less' => strncasecmp('apple', 'Banana', 3) <=> 0,
'greater' => strncasecmp('Zebra', 'apple', 3) <=> 0,
'equal' => strncasecmp('ABCdef', 'abcXYZ', 3) <=> 0,
'shorter' => strncasecmp('abc', 'ABCD', 10) <=> 0,
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);{"less":-1,"greater":1,"equal":0,"shorter":-1}The last entry shows that $length is only a limit. Both strings are shorter than ten characters, so the comparison covers abc and ABCD. The shorter string sorts first, so the sign is negative.
Example 3: zero and negative lengths
echo strncasecmp('abc', 'xyz', 0), "\n";
try {
strncasecmp('abc', 'abd', -1);
} catch (ValueError $e) {
echo get_class($e), "\n";
}0 ValueError
With a length of 0, even completely different strings count as equal. A negative length is rejected with a ValueError, so validate any length that comes from user input.
Edge cases
- Empty prefix: if
$lengthis computed from an empty string, it is0and the result is always0. A helper such as the one above therefore reports that every string starts with an empty prefix. Guard against it if that is not what you want. - Length larger than the strings: the comparison simply covers the full strings. If one string is shorter and everything before its end matches, the shorter one is considered less.
- Bytes, not characters: the function works on bytes. For multibyte text a length in bytes may cut a character in half, so use the
mb_string functions when you need character-aware comparison. - Embedded null bytes: because the function is binary safe, they are compared like any other byte.
Common mistakes
- Treating the result as a boolean.
if (strncasecmp($a, $b, 3))is true when the strings are different, because0means equal. Compare explicitly with=== 0. - Expecting a length difference. Code that reads the magnitude of the result as a distance breaks, since only the sign carries meaning.
- Using the wrong length. Passing
strlen($text)instead ofstrlen($prefix)turns a prefix check into a near full comparison. - Forgetting that case-insensitive is not accent-insensitive. The function does not make different letters equal; it only ignores case differences.
- Passing a negative length computed from arithmetic such as
strlen($a) - 10.
Related functions
strncmp()is the case-sensitive version of this comparison.strcasecmp()compares whole strings without regard to case.substr_compare()compares from an offset and can optionally ignore case.substr()extracts part of a string before comparing.stristr()searches case-insensitively for a substring.preg_match()handles more complex patterns.
Recap
strncasecmp() compares up to $length bytes of two strings and ignores case. It returns a negative number, zero or a positive number, and only the sign is meaningful. Use === 0 to test for equality, avoid negative lengths, and remember that a length of 0 always compares equal.
Tested examples
function startsWithIgnoreCase(string $text, string $prefix): bool
{
return strncasecmp($text, $prefix, strlen($prefix)) === 0;
}
var_dump(startsWithIgnoreCase('Help me', 'help'));
var_dump(startsWithIgnoreCase('Hello John', 'hello Doe'));
var_dump(strncasecmp('Hello John', 'hello Doe', 5));bool(true) bool(false) int(0)
$result = [
'less' => strncasecmp('apple', 'Banana', 3) <=> 0,
'greater' => strncasecmp('Zebra', 'apple', 3) <=> 0,
'equal' => strncasecmp('ABCdef', 'abcXYZ', 3) <=> 0,
'shorter' => strncasecmp('abc', 'ABCD', 10) <=> 0,
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);{"less":-1,"greater":1,"equal":0,"shorter":-1}
echo strncasecmp('abc', 'xyz', 0), "\n";
try {
strncasecmp('abc', 'abd', -1);
} catch (ValueError $e) {
echo get_class($e), "\n";
}0 ValueError