strcasecmp

Compares two strings case-insensitively and returns a negative, zero or positive integer.

Signature
strcasecmp(string $string1, string $string2): int
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$string1stringThe first string.
$string2stringThe 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.