There are several ways to compare strings, depending on what you want to know.
Are they exactly the same? ===
<?php
var_dump("php" === "php");
var_dump("php" === "PHP");
bool(true)
bool(false)
Ignoring case: strcasecmp()
strcasecmp() returns 0 when the strings are equal, ignoring case.
<?php
var_dump(strcasecmp("php", "PHP") === 0);
bool(true)
Which comes first: strcmp()
strcmp() returns a negative number if the first string is smaller, 0 if they are equal, and a positive number if it is bigger. The exact size of the number may differ, so compare with < 0, === 0 or > 0.
<?php
var_dump(strcmp("apple", "banana") < 0);
var_dump(strcmp("same", "same") === 0);
var_dump(strcmp("b", "a") > 0);
bool(true)
bool(true)
bool(true)
Natural sorting: strnatcmp()
Computers sort "img10" before "img2", because 1 comes before 2. Humans expect img2 first. strnatcmp() sorts the way people do.
<?php
$files = ["img10.png", "img2.png", "img1.png"];
natsort($files);
echo implode(", ", $files);
img1.png, img2.png, img10.png
How similar are they?
<?php
similar_text("World", "Word", $percent);
echo round($percent, 1) . "%\n";
echo levenshtein("kitten", "sitting");
88.9%
3
levenshtein() counts how many single-character edits turn one string into the other. It is useful for “did you mean …?” suggestions.
Comparing secrets: hash_equals()
When you compare a token, a password hash or any secret, do not use ===. A normal comparison stops at the first different character. An attacker can measure tiny time differences to guess the secret one character at a time. This is called a timing attack.
hash_equals() takes the same time every time.
<?php
$known = "a1b2c3d4";
$sent = "a1b2c3d4";
var_dump(hash_equals($known, $sent));
bool(true)
The known value must come first and the user-supplied value second.
Remember the rule
===. For case-insensitive, strcasecmp(). For secrets and tokens, hash_equals().