strcasecmp
Compares two strings case-insensitively and returns a negative, zero or positive integer.
strcasecmp(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 sorts before string2, greater than 0 if it sorts after, and 0 if they are equal ignoring ASCII case.
Changelog
- PHP 8.2.0No longer guaranteed to return strlen($string1) - strlen($string2) for different-length strings; it may now return -1 or 1. Only the sign is meaningful.
- PHP 8.2.0Case folding no longer depends on the locale; only ASCII letters are folded.
strcasecmp is the case-insensitive twin of strcmp. It compares two strings byte by byte, folding ASCII A-Z to lowercase first, and reports which one sorts earlier.
When to reach for it
Comparing values where case is incidental: HTTP header names, email local parts, file extensions, country or currency codes, enum-like config values, and role names. It also makes a good comparator for usort when you want alphabetical order that does not put every capitalised entry ahead of the lowercase ones.
What trips people up
The classic bug is testing truthiness. if (strcasecmp($a, $b)) is true when the strings differ, because equality returns 0. Always compare explicitly with === 0.
Since PHP 8.2 the magnitude of the return value is no longer defined — it used to be the length difference, and now it may be -1 or 1. Code that used the number for anything other than its sign is broken on modern PHP.
It also folds only ASCII. strcasecmp('É', 'é') is not 0, and since 8.2 the locale no longer influences that. For Unicode-aware comparison use mb_strtolower() on both sides, or Collator::compare() from intl for proper language-sensitive ordering.
Example
When to use it
- Match an HTTP header name such as Content-Type regardless of how the client capitalised it
- Check a file extension against an allow-list without worrying about .JPG versus .jpg
- Sort a list of names alphabetically without capitalised entries jumping to the top
Frequently asked questions
What is the difference between strcasecmp and strcmp?
strcasecmp ignores ASCII letter case, so 'Hello' and 'hello' compare as equal; strcmp treats them as different. Both return 0 for equal strings and a signed integer otherwise.
Why does strcasecmp return 0 when the strings match?
It is a comparison function, not an equality test: 0 means "neither sorts before the other". Write strcasecmp($a, $b) === 0 to test for equality rather than relying on truthiness.
Does strcasecmp work with accented or non-ASCII characters?
No. Since PHP 8.2 it folds ASCII A-Z only and ignores the locale, so É and é are not considered equal. Use mb_strtolower() on both strings or Collator::compare() from the intl extension.
More examples
Case-insensitive alphabetical sorting
The usort result is Alpha, Bravo, charlie, delta. Plain sort() uses byte order, so it puts Alpha and Bravo first only because uppercase letters have lower byte values, then charlie and delta — the ordering breaks as soon as casing is mixed within a letter.
<?php
$names = ['delta', 'Alpha', 'charlie', 'Bravo'];
usort($names, 'strcasecmp');
print_r($names);
$plain = ['delta', 'Alpha', 'charlie', 'Bravo'];
sort($plain);
print_r($plain);The truthiness trap
The condition is falsy because equal strings return 0, so "equal" prints from the else branch. The var_dump shows the correct explicit test returning true.
<?php
$a = 'Yes';
$b = 'yes';
if (strcasecmp($a, $b)) {
echo "looks equal but this branch means DIFFERENT\n";
} else {
echo "equal\n";
}
var_dump(strcasecmp($a, $b) === 0);ASCII-only folding
Plain ASCII folds correctly, but É and é are compared as raw bytes and do not match. Lowercasing with mb_strtolower first gives the expected true.
<?php
var_dump(strcasecmp('CAFE', 'cafe') === 0); // bool(true)
var_dump(strcasecmp('CAFÉ', 'café') === 0); // bool(false)
var_dump(mb_strtolower('CAFÉ') === mb_strtolower('café'));
Discussion