Comparaison de chaînes en utilisant '==' vs 'strcmp ()'


334

Il semble que l' ===opérateur de PHP soit sensible à la casse. Y a-t-il donc une raison d'utiliser strcmp()?

Est-il sûr de faire quelque chose comme ce qui suit?

if ($password === $password2) { ... }

10
Quel est le rapport avec la casse strcmp?
kennytm

1
@KennyTM: strcmpest sensible à la casse. Dans certaines langues, comme VB, la comparaison de chaînes peut ne pas l'être, et retournerait donc un résultat différent. Ce n'est cependant pas le cas en PHP.
cHao

13
@jie: Vous voudrez peut-être utiliser ===au lieu de ==parce que '0XAB' == '0xab'c'est vrai.
kennytm

17
utiliser === au lieu de == est important, car comparer n'importe quelle chaîne à 0 avec == retournera vrai, ce qui est évidemment faux ...
Karl Adler

4
@Kenny Aussi '0xAB' == '171'
Antimony

Réponses:


329

La raison de l'utiliser est parce que strcmp

renvoie <0 si str1 est inférieur à str2; > 0 si str1 est supérieur à str2 et 0 s'ils sont égaux.

===renvoie uniquement trueou false, il ne vous indique pas quelle est la "plus grande" chaîne.


9
icic tho dans mon cas actuel, je n'ai pas besoin de savoir quelle chaîne est la plus grande :)
Jiew Meng

155
strcmp avec les chaînes correspondantes a pris 0,207852 secondes strcmp avec les chaînes non correspondantes a pris 0,215276 secondes === avec les chaînes correspondantes a pris 0,067122 secondes === avec les chaînes non correspondantes a pris 0,057305 secondes snipplr.com/view/758

3
L'autre utilisation de strcmp montre le tri. Pour être plus clair sur le tri. strcmp () renvoie <0 si string1 trie avant string2,> 0 si string2 trie avant string1 ou 0 s'ils sont identiques. Par exemple $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); retournera supérieur à zéro, car aaao trie avant aabo.
HTML Man

20
Pourquoi cette réponse obtient-elle le plus de votes positifs? Je downvoting parce que bien que ce soit la réponse que cette question mérite mais pas la «bonne» réponse. La bonne réponse devrait être «Utiliser ===» comme beaucoup de gens l'ont déjà dit dans d'autres réponses.
onur güngör

2
En fait @onur Güngör, cela ne répond à la question de l'op, qui est So is there any reason to use strcmp() ?, alors que la réponse de Postfuturist ne fonctionne pas. Oh, l' enfer ... pas de réponse semblait compiler à la fois l' utilisation de strcmp()l' exécution de ===, et la mauvaise fiabilité des ==comparaisons de chaînes ... donc je le mien ajouté à la liste.
Balmipour

222

Vous ne devez jamais utiliser ==pour la comparaison de chaînes. ===est OK.

$something = 0;
echo ('password123' == $something) ? 'true' : 'false';

Exécutez simplement le code ci-dessus et vous comprendrez pourquoi.

$something = 0;
echo ('password123' === $something) ? 'true' : 'false';

Maintenant, c'est un peu mieux.


19
== n'est pas seulement un problème pour différents types. Cela donnera parfois des résultats inattendus même si les deux côtés sont une chaîne. Essayez '1e3' == '1000'
Antimony

3
comment 0 == 'password123'?
Andy Lobel

24
@AndyLobel PHP contraint 'password123' à un nombre en utilisant ses règles de comparaison lâches étranges puisque l'autre opérande est un nombre, cette chaîne, comme la plupart, contraint au nombre 0, et PHP renvoie vrai pour la comparaison.
postfuturiste

8
Un var_dump rapide ((int) 'password123'); m'a aidé à comprendre pourquoi cela s'est produit ... ** embarrassé ** ... j'aime vraiment l'opérateur ===
Carlton

3
c'est beacuse en utilisant '==' si l'un des deux opérandes peut être converti en nombre, php convertit les deux opérandes en nombres, et plus encore, si une chaîne non numérique est convertie en nombre, elle prend la valeur zéro, le résultat étant égal à zéro, donc le résultat de la comparaison avec un simple '==' peut quelque chose de indésirable
Luca C.

98

Ne pas utiliser ==en PHP. Il ne fera pas ce que vous attendez. Même si vous comparez des chaînes à des chaînes, PHP les convertira implicitement en flottants et effectuera une comparaison numérique si elles apparaissent numériques.

Par exemple, '1e3' == '1000'renvoie true. Vous devriez utiliser à la ===place.


16
Mais vous pouvez simplement ===.
Roman Newaza

11
@Roman oui mais beaucoup de programmeurs PHP ne savent pas qu'ils doivent le faire. D'où l'avertissement.
Antimony

5
@Antimony Alors pourquoi ne pas leur dire ce qu'ils devraient faire dans votre réponse?
Tim

43

Eh bien ... selon ce rapport de bogue php , vous pouvez même obtenir 0wned.

<?php 
    $pass = isset($_GET['pass']) ? $_GET['pass'] : '';
    // Query /?pass[]= will authorize user
    //strcmp and strcasecmp both are prone to this hack
    if ( strcasecmp( $pass, '123456' ) == 0 ){
      echo 'You successfully logged in.';
    }
 ?>

Il vous donne un avertissement, mais contourne toujours la comparaison.
Vous devriez faire ===comme l'a suggéré @postfuturist.


5
Wow +1. Citation du lien: "C'est un comportement établi pour une fonction qui reçoit le mauvais type d'argument (s) de retourner null". C'est étonnant étant donné que le manuel dit simplement ceci: "Renvoie <0 si str1 est inférieur à str2;> 0 si str1 est supérieur à str2 et 0 s'ils sont égaux". Null n'est pas mentionné comme une possibilité, mais sur des pages telles que la page de manuel substr, il est mentionné. soupir
Gerry

Mais en est-il de même lorsque la méthode du formulaire est post ...?
3lokh

@NikhilGeorge Oui, la fonction en question ici est strcmp. Peu importe les entrées comparées.
Ajith

Bien que le rapport de bogue indique qu'il était correct de retourner la valeur null, c'est incorrect. Toutes les versions officielles de PHP de PHP 4.3 à PHP 7.3 ne renvoient pas la valeur null de ces fonctions. Je soupçonne qu'il s'agissait peut-être d'une version alpha ou bêta, et indépendamment du fait que le bogue fermé soit invalide, il a été corrigé. Voir 3v4l.org/Zq8tM pour plus de détails, qui montrent que cela affecte HHVM 3.11 - 3.19.
Timo Tijhof

33

Rappelez-vous toujours que lorsque vous comparez des chaînes, vous devez utiliser l' ===opérateur (comparaison stricte) et non l' == opérateur (comparaison lâche).


8
En fait, je pense qu'il est prudent de dire que vous devriez utiliser ===pour comparer quoi que ce soit .
rink.attendant.6

22

Résumant toutes les réponses:

  • ==est une mauvaise idée pour les comparaisons de chaînes.
    Il vous donnera des résultats "surprenants" dans de nombreux cas. Ne lui faites pas confiance.

  • === est très bien, et vous donnera les meilleures performances.

  • strcmp() doit être utilisé si vous devez déterminer quelle chaîne est "supérieure", généralement pour les opérations de tri.


20

L'utilisation ==peut être dangereuse.

Notez qu'il transtyperait la variable dans un autre type de données si les deux diffèrent.

Exemples:

  • echo (1 == '1') ? 'true' : 'false';
  • echo (1 == true) ? 'true' : 'false';

Comme vous pouvez le voir, ces deux types sont de types différents, mais le résultat est true, ce qui n'est peut-être pas ce à quoi votre code s'attendra.

L' utilisation ===est toutefois recommandé comme le montre l'essai qu'il est un peu plus rapide que strcmp()et son alternative insensible à la casse strcasecmp().

La recherche rapide sur Google crie cette comparaison de vitesse: http://snipplr.com/view/758/


1
Parfois, il les jette dans un type différent même s'ils ont déjà le même type.
Antimony

même en comparant deux chaînes qui représentaient un entier comme "012" == "12"php, le type des deux chaînes a été changé en entier 12 == 12, puis retourné true.
GoTo



4

Vous pouvez utiliser strcmp()si vous souhaitez commander / comparer des chaînes lexicographiquement . Si vous souhaitez simplement vérifier l'égalité, ==c'est très bien.


1
Comme dans usort . En fait, c'est à peu près fait pour le tri.
Charles

@Charles Merci. Wikipédia a fait glacer mes yeux.
cbednarski

1
Pour être plus clair sur le tri. strcmp () renvoie <0 si string1 trie avant string2,> 0 si string2 trie avant string1 ou 0 s'ils sont identiques. Par exemple $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); retournera supérieur à zéro, car aaao trie avant aabo.
HTML Man

@postfuturist Je suis sûr que c'est une faute de frappe et ils voulaient dire ===.
ash

4

La fonction peut également aider au tri. Pour être plus clair sur le tri. strcmp () renvoie moins de 0 si string1 trie avant string2, supérieur à 0 si string2 trie avant string1 ou 0 s'ils sont identiques. Par exemple

$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string,$second_string);

La fonction renverra plus de zéro, car aaao trie avant aabo.


0

PHP Au lieu d'utiliser le tri alphabétique, utilisez la valeur ASCII du caractère pour effectuer la comparaison. Les lettres minuscules ont une valeur ASCII plus élevée que les majuscules. Il est préférable d'utiliser l'opérateur d'identité === pour effectuer ce genre de comparaison. strcmp () est une fonction permettant d'effectuer des comparaisons de chaînes sécurisées binaires. Il prend deux chaînes comme arguments et renvoie <0 si str1 est inférieur à str2; > 0 si str1 est supérieur à str2 et 0 s'ils sont égaux. Il existe également une version insensible à la casse nommée strcasecmp () qui convertit d'abord les chaînes en minuscules, puis les compare.


0

if ($password === $password2) { ... }n'est pas une chose sûre à faire lors de la comparaison de mots de passe ou de hachages de mots de passe lorsque l'une des entrées est contrôlée par l'utilisateur.
Dans ce cas, il crée un oracle de synchronisation permettant à un attaquant de dériver le hachage de mot de passe réel à partir des différences de temps d'exécution.
Utilisez-le à la if (hash_equals($password, $password2)) { ... }place, car hash_equals effectue une "comparaison sécurisée des chaînes de l'attaque temporelle".

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.