International PHP Conference 2019 - Spring Edition


(PHP 4, PHP 5, PHP 7)

strcmpBinary safe string comparison


int strcmp ( string $str1 , string $str2 )

Note that this comparison is case sensitive.



The first string.


The second string.

Return Values

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.


Example #1 strcmp() example

$var2 "hello";
if (
strcmp($var1$var2) !== 0) {
'$var1 is not equal to $var2 in a case sensitive string comparison';

See Also

  • strcasecmp() - Binary safe case-insensitive string comparison
  • preg_match() - Perform a regular expression match
  • substr_compare() - Binary safe comparison of two strings from an offset, up to length characters
  • strncmp() - Binary safe string comparison of the first n characters
  • strstr() - Find the first occurrence of a string
  • substr() - Return part of a string

add a note add a note

User Contributed Notes 25 notes

jendoj at gmail dot com
6 years ago
If you rely on strcmp for safe string comparisons, both parameters must be strings, the result is otherwise extremely unpredictable.
For instance you may get an unexpected 0, or return values of NULL, -2, 2, 3 and -3.

strcmp("5", 5) => 0
strcmp("15", 0xf) => 0
strcmp(61529519452809720693702583126814, 61529519452809720000000000000000) => 0
strcmp(NULL, false) => 0
strcmp(NULL, "") => 0
strcmp(NULL, 0) => -1
strcmp(false, -1) => -2
strcmp("15", NULL) => 2
strcmp(NULL, "foo") => -3
strcmp("foo", NULL) => 3
strcmp("foo", false) => 3
strcmp("foo", 0) => 1
strcmp("foo", 5) => 1
strcmp("foo", array()) => NULL + PHP Warning
strcmp("foo", new stdClass) => NULL + PHP Warning
strcmp(function(){}, "") => NULL + PHP Warning
lehal2 at hotmail dot com
5 years ago
i hope this will give you a clear idea how strcmp works internally.

= "b";
ord($str1); //98
echo "<br/>";
$str2 = "t";
ord($str2); //116
echo "<br/>";
$str1 = "bear";
$str2 = "tear";
$str3 = "";
strcmp($str1, $str2); // -18
echo "<br/>";
strcmp($str2, $str1); //18
echo "<br/>";
strcmp($str2, $str2); //0
echo "<br/>";
strcmp($str2, $str3); //4
echo "<br/>";
strcmp($str3, $str2); //-4
echo "<br/>";
strcmp($str3, $str3); // 0
echo "</pre>";
Rob Wiesler
9 years ago
One big caveat - strings retrieved from the backtick operation may be zero terminated (C-style), and therefore will not be equal to the non-zero terminated strings (roughly Pascal-style) normal in PHP. The workaround is to surround every `` pair or shell_exec() function with the trim() function. This is likely to be an issue with other functions that invoke shells; I haven't bothered to check.

On Debian Lenny (and RHEL 5, with minor differences), I get this:

= `pwd`;
$ps = "/var/www";

"Zero-terminated string:<br />sz = ".$sz."<br />str_split(sz) = "; print_r(str_split($sz));
"<br /><br />";

"Pascal-style string:<br />ps = ".$ps."<br />str_split(ps) = "; print_r(str_split($ps));
"<br /><br />";

"Normal results of comparison:<br />";
"sz == ps = ".($sz == $ps ? "true" : "false")."<br />";
"strcmp(sz,ps) = ".strcmp($sz,$ps);
"<br /><br />";

"Comparison with trim()'d zero-terminated string:<br />";
"trim(sz) = ".trim($sz)."<br />";
"str_split(trim(sz)) = "; print_r(str_split(trim($sz))); echo "<br />";
"trim(sz) == ps = ".(trim($sz) == $ps ? "true" : "false")."<br />";
"strcmp(trim(sz),ps) = ".strcmp(trim($sz),$ps);

Zero-terminated string:
sz = /var/www
str_split(sz) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w [8] => )

Pascal-style string:
ps = /var/www
str_split(ps) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w )

Normal results of comparison:
sz == ps = false
strcmp(sz,ps) = 1

Comparison with trim()'d zero-terminated string:
trim(sz) = /var/www
str_split(trim(sz)) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w )
trim(sz) == ps = true
strcmp(trim(sz),ps) = 0
frewuill at merlin-corp dot com
18 years ago
Hey be sure the string you are comparing has not special characters like '\n' or something like that.
16 years ago
In summary, strcmp() does not necessarily use the ASCII code order of each character like in the 'C' locale, but instead parse each string to match language-specific character entities (such as 'ch' in Spanish, or 'dz' in Czech), whose collation order is then compared. When both character entities have the same collation order (such as 'ss' and '' in German), they are compared relative to their code by strcmp(), or considered equal by strcasecmp().
The LC_COLLATE locale setting is then considered: only if LC_COLLATE=C or LC_ALL=C does strcmp() compare strings by character code.
Generally, most locales define the following order:
control, space, punctuation and underscore, digit, alpha (lower then upper with Latin scripts; or final, middle, then isolated, initial with Arabic script), symbols, others...
With strcasecmp(), the alpha subclass is ignored and consider all forms of letters as equal.
Note also that some locales behave differently with accented characters: some consider they are the same letter as the unaccented letter (with a minor collation order, e.g. French, Italian, Spanish), some consider they are distinct letters with an independant collation order (e.g. in the C locale, or in Nordic languages).
Finally, the collation string is not considering individual characters but instead groups of characters that form a single letter:
- for example "ch" or "CH" in Spanish which is always after all other strings beginning with 'c' or 'C', including "cz", but before 'd' or 'D';
- 'ss' and '' in German;
- 'dz', 'DZ' and 'Dz' in some Central European languages written with the Latin script...
- UTF-8, UTF-16 (Unicode), S-JIS, Big5, ISO2022 character encoding of a locale (the suffix in the locale name) first decode the characters into the UCS4/ISO10646 code position before applying the rules of the language indicated by the main locale...
So be extremely careful to what you consider a "character", as it may just mean a encoding byte with no significance in the string collation algorithm: the first character of the string "cholera" in Spanish is "ch", not "c" !
hrodicus at gmail dot com
7 years ago
Note a difference between 5.2 and 5.3 versions

echo (int)strcmp('pending',array());
will output -1 in PHP 5.2.16 (probably in all versions prior 5.3)
but will output 0 in PHP 5.3.3

Of course, you never need to use array as a parameter in string comparisions.
chris at unix-ninja dot com
5 years ago
Since it may not be obvious to some people, please note that there is another possible return value for this function.

strcmp() will return NULL on failure.

This has the side effect of equating to a match when using an equals comparison (==).
Instead, you may wish to test matches using the identical comparison (===), which should not catch a NULL return.


$variable1 = array();
$ans === strcmp($variable1, $variable2);

This will stop $ans from returning a match;

Please use strcmp() carefully when comparing user input, as this may have potential security implications in your code.
hm2k at php dot net
8 years ago
Don't forget the similar_text() function...
kamil dot k dot kielczewski at gmail dot com
11 months ago
Vulnerability (in PHP >=5.3) :

if (strcmp($_POST['password'], 'sekret') == 0) {
"Welcome, authorized user!\n";
} else {
"Go away, imposter.\n";

$ curl -d password=sekret
Welcome, authorized user!

$ curl -d password=wrong
Go away, imposter.

$ curl -d password[]=wrong
Welcome, authorized user!

SRC of this example:
wsogmm at seznam dot cz
9 years ago
Just a short comment to the note of arnar at hm dot is: md5() is a hash function and therefore it may happen (although it is very unlikely) that the md5() checksums of  two different strings will be equal (hash collision) ...
jcanals at totsoft dot com
14 years ago
Some notes about the spanish locale. I've read some notes that says  "CH", "RR" or "LL" must be considered as a single letter in Spanish. That's not really tru. "CH", "RR" and "LL" where considered a single letter in the past (lot of years ago), for that you must use the "Tradictional Sort". Nowadays, the Academy uses the Modern Sort and recomends not to consider anymore "CH", "RR" and "LL" as a single letter. They must be considered two separated letters and sort and compare on that way.

Ju just have to take a look to the Offial Spanish Language Dictionary and you can see there that from many years ago there is not the separated section for "CH", "LL" or "RR" ... i.e. words starting with CH must be after the ones starting by CG, and before the ones starting by CI.
M. Egmond
12 years ago
php dot or dot die at phpuser dot net wrote that he had an unexpected difference in comparing between case sensitive and insensitive. They key there is that the case insensitive comparison converts both strings to lowercase before comparing. Since the underscore character is in a different place when compared to an uppercase or lowercase string, the result is different.

There is no 'clear' order of punctuation and other characters in or around the alphabet. Most code assumes ASCII order in which case there are several characters before both upper- and lowercase, a few inbetween, and some after both upper- and lowercase.

Note also many other/older implementations of sorting sort accented character wrong since they appear after all other alphabetical characters in most charactersets. There is probably a function in PHP to take this into account though.

Therefore I would not recommend to make a detailed assumption on how punctuation and other characters sort in relation to alphabetical characters. If sorting these characters at a specific place and in a specific order is important for you, you should probably write a custom string comparison function that does it the way you want. Usually it's sufficient to have a consistent sorting order though, which is what you get by using either strcmp, or strcasecmp consistently.
8 months ago
strcmp returns strlen($str1)-strlen($str2) when one string is the part of the other string. Otherwise it returns -1 or 1 if two strings are not identical and 0 when they are.

echo strcmp("Hello world!","Hworld")."<br>"//-1
echo strcmp("Hello world!","Hello")."<br>";     //7
echo strcmp("Hello world!","Hworld world! Hello!")."<br>"; //-1
echo strcmp("Hello world!","Hello world! Hello!")."<br>";    //-7
luizvid at gmail dot com
3 years ago
strcmp returns -1 ou 1 if two strings are not identical,
and 0 when they are, except when comparing a string and an empty string (<?php $a = ""?>), it returns the length of the string.

For instance:
= "foo"; // length 3
$b = ""; // empty string
$c = "barbar"; // length 6

echo strcmp($a, $a); // outputs 0
echo strcmp($a, $c); // outputs 1
echo strcmp($c, $a); // outputs -1
echo strcmp($a, $b); // outputs 3
echo strcmp($b, $a); // outputs -3
echo strcmp($c, $b); // outputs 6
echo strcmp($b, $c); // outputs -6
jeff at skrysak dot com
12 years ago
The definition of return values of this function is listed correctly on this page, however, there is a common misconception in the notes posted here previously from users.

A previous poster said:
If $str1 == $str2 strcmp return 0.
If $str1  > $str2 strcmp return 1.
If $str1  < $str2 strcmp return -1.

That is incorrect, please look at the definition of the function
at the top of this page. It returns less than 0 if str1 is less than str2. Note the phrase "less than", it does not return just -1, but any negative value. The same happens when str1 is greater than str2, but it returns a positive, non-zero value. It returns a positive value that can be 1, or any number thereafter.

strcmp() returns a number that is the difference between the two strings starting with the last character that was found to be similar.

Here is an example:

$output = strcmp("red", "blue");

The variable $output with contain a value of 16
admin[nospam] at pretend dot tk
15 years ago
Reguarding the above note on language specific string comparisons, LL and RR are also single letters in the Spanish language.
izhan dot khalib at acpibhd dot com
15 years ago
I have tried the  strcmp function. Pls be very carefull. The string comparison must exactly "equal". So many people had confused.


My program read a string from test.txt file to get the
"[company name]" string.

// get contents of a file into a string
$filename = "test.txt";
$fd = fopen ($filename, "rb");
$contents = fread ($fd, filesize ($filename));

for($i=0;$i<strpos($contents, "]")+1;$i++)
//print $contents[$i];
echo $a;
//echo $i;


// this comparison will resulted on greater (1), $result=1
//please remember $tempvariable[2] != $tempvariable (is not equal)
$result = strcmp(strtolower($a),strtolower($str2));

//this comparison working properly, $result=0
//$result = strcmp(strtolower($a),strtolower($str2[12]));

echo $result;

if ($a==$str2[12]) //double check the equality of string
echo "read the NextLine"; }
else {
echo "not equal";

fclose ($fd);

I hope the above example will help you.
arnar at hm dot is
9 years ago
Sometimes when you compare two strings that look "the same", you will find that they aren't. If you don't want to bother finding out why, then this is a simple solution:

$string = implode(str_split($string));

Converting the strings to md5 is also a nice method to see if they're equal.


Arnar Yngvason
gregd at sad dot net
15 years ago
In cases when you need to compare a line from a just parsed file stream to match a user-defined "nametag" (useful for parsing ini and configuration files), keep in mind the 'end of line' tags as well:

// nametag to look for in a file (notice a required "\r\n" at the end)
$nametag = "[System]\r\n";

// ...assuming the file has been aready opened for reading and the stream is bound to $filehandle... parse the file until an EOF or $nametag encountered.

while (!feof ($handle))
    $buffer = fgets($filehandle);
    if (strcmp($nametag, $buffer) == 0)
        // at this point "[System]" is found, do additional parsings...
nullhility at gmail dot com
9 years ago
For those that are confused about the way this function works:

= 'a';
$str2 = 'b';
var_dump(strcmp($str1, $str2)); //int(-1)

Alphabetically 'a' precedes 'b'. If we view the strings as values 'a' is less than 'b' and therefore the function returns -1.

If we were searching through an alphabetically sorted list we'd have a numerical index ($i) and compare the search string ($sstr) against each member of the string list ($slist), using strcmp we can check whether to go "up"($i++) or "down"($i--) through this list.

Here's the example function:
function strInList ($sstr)
$slist = array('a', 'b', 'c', 'd', 'e' /* etc */);
$i = sizeof($slist) / 2; //start the index in the middle
while ($i < sizeof($slist) && $i >= 0) { //constrain $i to the scope of $slist
$cmp = strcmp($slist[$i], $sstr);
        if (
$cmp > 0) { //alphabetically, $slist[$i] procedes $sstr
$i--; //move DOWN the list
} else if ($cmp < 0) { //alphabetically, $slist[$i] precedes $sstr
$i++; //move UP the list
} else if ($cmp == 0) { //$slist[$i] occurs neither before nor after $sstr
return true; //successful match
false; //The index fell out of the list scope, with no match made
francis at flourish dot org
12 years ago
If you want to strings according to locale, use strcoll instead.
element @ no spam dot net
13 years ago
When using strcmp to compare results received from a form, keep in mind that the way you decide to encapsulate the value of the form will have an effect on your strcmp() results.


<input type="post" name="user[0]" value="abc">
<input type="post" name="user[1]" value='abc'>

strcmp() will not return the values sent from this form as "0".

However, by using single-quotes or double-quotes to encapsulate BOTH values, strcmp() will return a "0" result.
madsen at sjovedyr dot dk
16 years ago
It's definitely worth noting that the return-values of strcmp() when used for i.e. password-checking is the oposite of that of the ==-operator.

$pw1 = "yeah";
$pw2 = "yeah";

if (strcmp($pw1, $pw2)) {   // This returns false.
    // $pw1 and $pw2 are NOT the same.
} else {
    // $pw1 and $pw2 are the same.

Where the use of the == operator would give us.:
if ($pw1==$pw2) {    // This returns true.
    // $pw1 and $pw2 are the same.
} else {
    // $pw1 and $pw2 are NOT the same.

Additionally, to check if $pw1 and $pw2 are of the same type you can use the === operator.
owen at cips dot nokia dot com
17 years ago
Regarding bizarre return values from str*cmp(), I was having similar troubles until I realized that I was attempting to compare a string with HTML formatting with its plain-text equivilant. The formatted string was an <OPTION> value, so the HTML was rendered without the <b> and <i> formatting I was using. Consequently the formatted and unformatted strings were rendered identically in the browser. D'oh!
g-lock at
10 years ago
Here is my function to compare russian words.
You can replace $abc to your alphabet.

function strcmp_rus($str1, $str2)
    $len = min(strlen($str1), strlen($str2));
    for ($i = 0; $i < $len; $i++)
        $s1 = strlen($abc);
        $s2 = strlen($abc);
        for ($j = 0; $j < strlen($abc); $j++) if ($str1[$i] == $abc[$j]) $s1 = $j;
        for ($k = 0; $k < strlen($abc); $k++) if ($str2[$i] == $abc[$k]) $s2 = $k;
        if ($s1 < $s2) return -1;
        else if ($s1 > $s2) return 1;   
    return 0;
To Top