Strings7 min readExamples run on PHP 8.5.10

strcasecmp()

Learn how PHP 8.4 strcasecmp() compares two strings ignoring ASCII case, how to read its return sign, and where it falls short.

Signature

strcasecmp(string $string1, string $string2): int

Purpose

strcasecmp() compares two strings while ignoring the difference between uppercase and lowercase ASCII letters. It answers three questions in one call: are the strings equal, does the first sort before the second, or does it sort after? The comparison is binary safe, so every byte counts, including NUL bytes. It does not depend on the current locale.

Reach for it when the text being compared is a protocol token, a command name, a file extension, a header name or any other identifier where Yes, YES and yes mean the same thing.

Signature

Parameters and defaults

  • $string1: the first string.
  • $string2: the second string.

Both parameters are required and there are no defaults. The function has no flags or options. If you need a limit on how many characters are compared, look at strncasecmp(). If you need to start at an offset, look at substr_compare().

Return value and failure cases

The function returns an int:

  • a value less than 0 when $string1 sorts before $string2,
  • a value greater than 0 when $string1 sorts after $string2,
  • exactly 0 when the strings are equal ignoring ASCII case.

Only the sign of the result has meaning. As of PHP 8.2 the function is no longer guaranteed to return the difference in string lengths when the lengths differ; it may return -1 or 1 instead. Never compare the result against a specific non-zero number such as -3. Test it against 0, or normalize it with the spaceship operator.

The function has no "not found" or false result. Passing a value that cannot be used as a string, such as an array, raises a TypeError.

Example 1: an equality check

The most common use is testing for equality. Compare the result with 0 using the strict operator.

Example
<?php
$a = "Hello";
$b = "hello";
echo json_encode(strcasecmp($a, $b) === 0), "\n";
Output
true

The two strings differ only in the case of one letter, so the result is 0 and the check is true.

Example 2: reading the sign

Because the exact number is not reliable, reduce the result to -1, 0 or 1 when you want a stable value to store, log or test.

Example
<?php
$pairs = [["apple", "Banana"], ["Cherry", "banana"], ["PHP", "php"]];
$result = [];
foreach ($pairs as [$left, $right]) {
    $result[] = strcasecmp($left, $right) <=> 0;
}
echo json_encode($result), "\n";
Output
[-1,1,0]

The first word sorts before the second, the second sorts after, and the last pair is equal.

Example 3: sorting without regard to case

The function follows the usual callback contract, so its name can be passed straight to usort().

Example
<?php
$names = ["delta", "Alpha", "charlie", "Bravo"];
usort($names, 'strcasecmp');
echo json_encode($names), "\n";
Output
["Alpha","Bravo","charlie","delta"]

A plain sort() would place the capitalized words first, because uppercase letters have lower byte values. With strcasecmp() the order follows the alphabet.

Edge cases

  • Only ASCII letters are folded. The comparison is not locale aware. Letters such as é and É are multibyte sequences, and their bytes differ, so they are not treated as equal. For Unicode-aware comparison, normalize both strings with the mb_* functions first.
  • Prefixes. A shorter string that is a prefix of a longer one sorts first, so strcasecmp("abc", "ABCD") is negative.
  • Empty strings. Two empty strings are equal, and an empty string sorts before any non-empty string.
  • Binary data. Embedded NUL bytes are compared like any other byte; they do not end the comparison.
  • Numeric strings. The values are compared as text, not as numbers. "10" sorts before "9".

Common mistakes

  1. Using a loose truth test. if (strcasecmp($a, $b)) is true when the strings are different, because equality returns 0, which is falsy. Write === 0 to make the intent clear.
  2. Depending on the magnitude. Code that expects the length difference breaks on PHP 8.2 and later. Use only the sign.
  3. Expecting Unicode folding. Case-insensitive comparison of accented or non-Latin text needs a multibyte-aware approach.
  4. Confusing it with strcmp(). strcmp() is case-sensitive, so "a" and "A" are different there.
  5. Using it for secrets. It is a general comparison function and is not designed for comparing passwords or tokens. Use hash_equals() for that purpose, with an exact-case value.
  • strcmp(): binary safe, case-sensitive comparison.
  • strncasecmp(): case-insensitive comparison limited to the first n bytes.
  • substr_compare(): compare from an offset, optionally ignoring case.
  • stristr(): case-insensitive search for a substring.
  • preg_match(): pattern matching with an i modifier for case-insensitive rules.
  • substr(): extract the part of a string you want to compare.

Recap

strcasecmp() takes two strings and returns a negative number, zero or a positive number. Zero means the strings are equal when ASCII letter case is ignored. Treat only the sign as meaningful, compare against 0 strictly, and remember that non-ASCII letters are not folded.

Tested examples

Case-insensitive equality check
<?php
$a = "Hello";
$b = "hello";
echo json_encode(strcasecmp($a, $b) === 0), "\n";
Output
true
Normalizing the result to its sign
<?php
$pairs = [["apple", "Banana"], ["Cherry", "banana"], ["PHP", "php"]];
$result = [];
foreach ($pairs as [$left, $right]) {
    $result[] = strcasecmp($left, $right) <=> 0;
}
echo json_encode($result), "\n";
Output
[-1,1,0]
Sorting names with usort()
<?php
$names = ["delta", "Alpha", "charlie", "Bravo"];
usort($names, 'strcasecmp');
echo json_encode($names), "\n";
Output
["Alpha","Bravo","charlie","delta"]