'=='と 'strcmp()'を使用した文字列比較


334

PHPの===演算子は大文字と小文字が区別されるようです。使用する理由はありますstrcmp()か?

次のようなことをしても安全ですか?

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

10
大文字と小文字の区別は何に関係していstrcmpますか?
kennytm

1
@KennyTM:strcmp大文字と小文字が区別されます。VBのような一部の言語では、文字列比較ができない場合があり、異なる結果を返します。ただし、これはPHPには当てはまりません。
cHao

13
@jie:がtrue ===である==ため、代わりに使用したい場合'0XAB' == '0xab'があります。
kennytm

17
==の代わりに===を使用することは重要です。文字列を0と==で比較するとtrueが返されますが、これは明らかにfalseです...
Karl Adler

4
@ケニーも '0xAB' == '171'
アンチモン

回答:


329

それを使う理由は strcmp

str1がstr2より小さい場合、<0を返します。> str1がstr2より大きい場合は0、それらが等しい場合は0。

===trueまたはだけを返しfalseます。どちらが「大きい」文字列であるかはわかりません。


9
icic tho私の現在のケースでは、どの文字列が大きいかを知る必要はありません:)
Jiew Meng

154
一致する文字列が一致しない文字列をstrcmpの0.207852秒を要したとのstrcmpは、一致する文字列で=== 0.215276秒かかりました0.067122秒かかりました===非一致する文字列は、0.057305秒かかりましたと snipplr.com/view/758

3
strcmpのその他の使用法は、ソートを示します。ソートについてより明確にするため。strcmp()は、string1がstring2の前にソートされる場合は<0を返し、string2がstring1の前にソートされる場合は> 0を返します。同じである場合は0を返します。たとえば、$ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp($ string_first、$ string_second); aaaoはaaboの前にソートしているため、ゼロより大きい値を返します。
HTMLマン

20
なぜこの回答が最も賛成票を獲得するのですか?この質問に値する答えですが、「正しい」答えではないので、私は反対票を投じています。多くの人がすでに他の答えで言っているので、正しい答えは「使用===」であるべきです。
onurgüngör2013年

2
@onurgüngör実際には、これ opの質問に回答ますがSo is there any reason to use strcmp() ?、Postfuturistの回答は回答しません。ああ、地獄...誰も答えが一度にコンパイルするために見えた使用strcmp()パフォーマンス===、そして悪い信頼性==私はリストに地雷を追加しましたので...文字列の比較のために。
Balmipour 2017

222

==文字列の比較には使用しないでください。===大丈夫です。

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

上記のコードを実行するだけで、その理由がわかります。

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

さて、それは少し良いです。


19
==は、異なるタイプの問題だけではありません。両側が文字列であっても、予期しない結果になることがあります。「1e3」==「1000」を試してください
アンチモン

3
0 == 'password123'はどうですか?
Andy Lobel 2012

24
@AndyLobel PHPは、 'password123'を奇数の緩い比較ルールを使用して数値に強制変換します。これは、他のオペランドが数値であるため、その文字列は、ほとんどの場合、0に強制変換され、PHPは比較に対してtrueを返します。
未来派

8
簡単なvar_dump((int) 'password123'); これがなぜ起こったのかを完全に理解するのに役立ちました... **恥ずかしい** ... ===演算子が本当に好きです
Carlton

3
これは、2つのオペランドの1つが数値にキャスト可能で、phpが両方のオペランドを数値にキャストする場合、「==」を使用するので、非数値文字列が数値にキャストされる場合、値はゼロになり、結果はゼロに等しくなります。したがって、単純な '=='との比較の結果は望ましくない可能性があります
Luca C.

98

使わない ==PHPでは。それはあなたが期待することをしません。文字列を文字列と比較している場合でも、PHPはそれらを暗黙的に浮動小数点数にキャストし、数値と思われる場合は数値比較を行います。

たとえば、'1e3' == '1000'trueを返します。===代わりに使用する必要があります。


16
しかし、===することもできます。
Roman Newaza 2013年

11
@Romanはい、しかし多くのPHPプログラマーはそれをしなければならないことを知りません。したがって警告。
アンチモン2013年

5
@Antimonyそれで、あなたの答えで彼らが何をすべきか彼らに言ってみませんか?
Tim

43

まあ..このphpバグレポートによると、あなたは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.';
    }
 ?>

警告が表示されますが、比較はバイパスされます。@postfuturistの提案に従っ
てください===


5
すごい+1。リンクからの引用:「関数が誤ったタイプの引数を受け取ってnullを返すのは、確立された動作です。」マニュアルに次のように書かれていることを考えると、それは驚くべきことです。「str1がstr2より小さい場合は<0を返し、str1がstr2より大きい場合は> 0を返し、等しい場合は0を返します」。nullは可能性として言及されていませんが、substrのmanページなどのページでは言及されています。ため息
ジェリー

しかし、formメソッドがpostの場合も同じですか?
3lokh、2014

@NikhilGeorgeそうです、ここで問題となっている関数はstrcmpです。どの入力が比較されるかは関係ありません。
2014年

バグレポートではnullを返すのは問題ないと述べていますが、これは誤りです。PHP 4.3からPHP 7.3までのすべての公式PHPリリースは、これらの関数からnullを返しません。私はそれがアルファまたはベータリリースであったかもしれないと思います、そして閉じられているバグが無効であるにもかかわらず、それは修正されました。詳細については3v4l.org/Zq8tMを参照してください。これは、HHVM 3.11〜3.19に影響を与えることを示しています。
Timo Tijhof

33

文字列を比較するときは、===演算子(厳密な比較)ではなく ==演算子(厳密な比較)を使用する必要があります。


8
実際、何を===比較するときでも使うべきだと言っても差し支えないと思います。
rink.attendant.6 2015年

22

すべての回答をまとめると:

  • ==ある悪い考え文字列比較のために。
    多くの場合、「驚くべき」結果が得られます。信用しないでください。

  • === 大丈夫です、そしてあなたに最高のパフォーマンスを与えます。

  • strcmp() 通常、並べ替え操作のために、どの文字列が「大きい」かを判断する必要がある場合に使用します。


20

使用==すると危険な場合があります。

2つが異なる場合、変数を別のデータ型にキャストすることに注意してください。

例:

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

ご覧のとおり、これらの2つは異なるタイプのものですが、結果はtrueであり、コードが期待するものとは異なる場合があります。

===ただし、を使用することをお勧めします。テストではstrcmp()、大文字と小文字を区別しない代替よりも少し高速であることを示していstrcasecmp()ます。

クイックグーグルはこの速度比較を叫びます:http : //snipplr.com/view/758/


1
すでに同じ型であっても、別の型にキャストする場合があります。
アンチモン2013

"012" == "12"phpのような整数を表す2つの文字列を比較する場合でも、両方の文字列の型を整数に変更して12 == 12返しtrueます。
GoTo


6

strcmpは、実行している環境(Linux / Windows)に基づいて異なる値を返します。

理由は、バグレポートにhttps://bugs.php.net/bug.php?id=53999と記載されているように、バグがあるためです

取り扱いには十分ご注意ください!!


ただし、文字列が等しい場合は常に0を返します。ただし、0以外の値に注意することには注意してください。
ファルケン教授の契約が2013年

4

strcmp()文字列を辞書的に順序付け /比較する場合に使用できます。等しいかどうかを確認するだけの場合は問題ありません==


1
usortのように。実際、それはソートのためにほとんど作られています。
Charles

@チャールズありがとう。ウィキペディアは私の目を艶やかにしました。
cbednarski

1
ソートについてより明確にするため。strcmp()は、string1がstring2の前にソートされる場合は<0を返し、string2がstring1の前にソートされる場合は> 0を返します。同じである場合は0を返します。たとえば、$ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp($ string_first、$ string_second); aaaoはaaboの前にソートしているため、ゼロより大きい値を返します。
HTMLマン

@postfuturist私はそれがタイプミスだと確信してい===ます。
アッシュは

4

また、関数はソートに役立ちます。ソートについてより明確にするため。strcmp()は、string1がstring2の前にソートされる場合は0未満を返し、string2がstring1の前にソートされる場合は0より大きいか、同じ場合は0を返します。例えば

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

aaaoはaaboの前にソートしているため、この関数はゼロより大きい値を返します。


0

PHPアルファベット順のソートを使用する代わりに、文字のASCII値を使用して比較を行います。小文字は大文字よりもASCII値が高くなります。この種の比較を行うには、識別演算子===を使用することをお勧めします。strcmp()は、バイナリセーフな文字列比較を実行する関数です。2つの文字列を引数として取り、str1がstr2より小さい場合は<0を返します。> str1がstr2より大きい場合は0、それらが等しい場合は0。文字列を小文字に変換してから比較するstrcasecmp()という名前の大文字小文字を区別しないバージョンもあります。


0

if ($password === $password2) { ... }入力の1つがユーザー制御であるパスワードまたはパスワードハッシュを比較する場合、安全ではありません。
その場合、攻撃者が実行時間の差から実際のパスワードハッシュを導出できるタイミングオラクルを作成します。hash_equalsは「タイミング攻撃に対する安全な文字列比較」を実行するため、代わりに
使用してください。if (hash_equals($password, $password2)) { ... }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.