Si votre chaîne est dans un codage à un seul octet, c'est simple :
if(strtolower($var1) === strtolower($var2))
Si votre chaîne est en UTF-8, vous devez tenir compte de la complexité de l'Unicode : to-lower-case et to-upper-case ne sont pas des fonctions bijectives, c'est-à-dire que si vous avez un caractère minuscule, que vous le transformez en majuscule et que vous le retransformez en minuscule, vous ne vous retrouverez pas forcément avec le même point de code (et il en va de même si vous commencez avec un caractère majuscule).
Par exemple
- "" (
Latin Capital Letter I with Dot Above, U+0130
) est un caractère majuscule, avec "i" ( Latin Small Letter I, U+0069
) comme variante en minuscule - et la variante en majuscule de "i" est "I" ( Latin Capital Letter I, U+0049
).
- "" (
Latin Small Letter Dotless I, U+0131
) est un caractère minuscule, avec "I" ( Latin Capital Letter I, U+0049
) comme variante en majuscule - et la variante en minuscule de "I" est "i" ( Latin Small Letter I, U+0069
)
Alors mb_strtolower('') === mb_strtolower('i')
renvoie faux, même s'ils ont le même caractère majuscule. Si vous voulez vraiment une fonction de comparaison de chaînes de caractères insensible à la casse, vous devez comparer la version en majuscules ET la version en minuscules :
if(mb_strtolower($string1) === mb_strtolower($string2)
|| mb_strtoupper($string1) === mb_strtoupper($string2))
J'ai lancé une requête dans la base de données Unicode à partir de https://codepoints.net ( https://dumps.codepoints.net ) et j'ai trouvé 180 points de code pour lesquels j'ai trouvé un caractère différent en prenant la minuscule de la majuscule du caractère, et 8 points de code pour lesquels j'ai trouvé un caractère différent en prenant la majuscule de la minuscule du caractère.
Mais il y a pire En effet, un même groupe de graphèmes vu par l'utilisateur peut avoir plusieurs façons de le coder : "ä" peut être représenté comme Latin Small Letter a with Diaeresis (U+00E4)
ou comme Latin Small Letter A (U+0061)
et Combining Diaeresis (U+0308)
- et si vous les comparez au niveau de l'octet, cela ne retournera pas vrai !
Mais il existe une solution pour cela dans Unicode : Normalisation ! Il existe quatre formes différentes : NFC, NFD, NFKC, NFKD. Pour la comparaison de chaînes de caractères, NFC et NFD sont équivalents et NFKC et NFKD sont équivalents. Je prendrais NFKC car il est plus court que NFKD, et "" ( Latin Small Ligature ff, U+FB00
) sera transformé en deux "f" normaux (mais 2 sera aussi étendu à 25 ).
La fonction résultante devient :
function mb_is_string_equal_ci($string1, $string2) {
$string1_normalized = Normalizer::normalize($string1, Normalizer::FORM_KC);
$string2_normalized = Normalizer::normalize($string2, Normalizer::FORM_KC);
return mb_strtolower($string1_normalized) === mb_strtolower($string2_normalized)
|| mb_strtoupper($string1_normalized) === mb_strtoupper($string2_normalized);
}
Veuillez noter :
- vous avez besoin de la intl pour le Normalisateur
- vous devriez optimiser cette fonction en vérifiant d'abord s'ils sont égaux^^.
- vous voudrez peut-être utiliser NFC au lieu de NFKC, car NFKC supprime trop de distinctions de formatage à votre goût
- vous devez décider par vous-même si vous avez vraiment besoin de toute cette complexité ou si vous préférez une variante plus simple de cette fonction.