'==' vs. 'strcmp ()' kullanarak dize karşılaştırması


334

PHP'nin ===operatörü büyük / küçük harfe duyarlıdır. Kullanmak için bir sebep var strcmp()mı?

Aşağıdaki gibi bir şey yapmak güvenli mi?

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

10
Büyük / küçük harf duyarlılığı ne ile ilgilidir strcmp?
kennytm

1
@KennyTM: strcmpbüyük / küçük harfe duyarlıdır. VB gibi bazı dillerde, dize karşılaştırması olmayabilir ve bu nedenle farklı bir sonuç döndürür. PHP'de durum böyle değil.
cHao

13
@jie: Sen kullanmak isteyebilirsiniz ===yerine ==çünkü '0XAB' == '0xab'doğrudur.
kennytm

17
== yerine === kullanmak önemlidir, çünkü herhangi bir dizeyi 0 ile == ile karşılaştırmak doğru olan yanlış döndürür ...
Karl Adler

4
@Kenny Ayrıca '0xAB' == '171'
Antimon

Yanıtlar:


329

Bunu kullanmanın nedeni strcmp

str1 str2'den küçükse <0 döndürür; Str1 str2'den büyükse> 0 ve eşitse 0.

===yalnızca döndürür trueya da false, hangisinin "büyük" dize olduğunu söylemez.


9
icic tho benim mevcut durumda, ben hangi dize daha büyük olduğunu bilmek gerekmez :)
Jiew Meng

154
eşleşen dizeleri ile strcmp 0.207852 saniye aldı Eşleşmeyen dizeleri ile strcmp 0.215276 saniye aldı === eşleşen dizeleri ile 0.067122 saniye === eşleşen dizeleri ile 0.057305 saniye aldı snipplr.com/view/758

3
Strcmp için diğer kullanım sıralama gösterir. Sıralama konusunda daha açık olmak. strcmp (), string1 string2'den önce sıralıyorsa <0, string2 string1'den önce sıralıyorsa 0 ya da aynıysa 0 değerini döndürür. Örneğin $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); aao aabo'dan önce sıralandığı için sıfırdan daha büyük dönecektir.
HTML Man

20
Bu cevap neden en fazla oyu alıyor? Aşağı düşüyorum çünkü bu sorunun hak ettiği cevap olmasına rağmen 'doğru' cevap değil. Birçok kişinin diğer cevaplarda zaten söylediği gibi, doğru cevap 'Use ===' olmalıdır.
onur güngör

2
@onur güngör Aslında bu yapar cevapları Op'un soru So is there any reason to use strcmp() ?Postfuturist cevabı yok iken,. Lanet olsun ... kimse cevap seferde derlemek gibiydi kullanım ait strcmp(), performans ve ===ve kötü güvenilirlik ve ==ben listesine mayın ekledi böylece ... dize karşılaştırmaları için.
Balmipour

222

==Dize karşılaştırması için asla kullanmamalısınız . ===tamam.

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

Sadece yukarıdaki kodu çalıştırın ve nedenini göreceksiniz.

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

Şimdi, bu biraz daha iyi.


19
== sadece farklı türler için bir problem değildir. Her iki taraf da bir dize olsa bile bazen beklenmedik sonuçlar verecektir. '1e3' == '1000' deneyin
Antimon

3
0 == 'password123' nasıl?
Andy Lobel

24
@AndyLobel PHP 'password123' ü tuhaf gevşek karşılaştırma kurallarını kullanarak bir sayıya zorlar, çünkü diğer işlenen bir sayıdır, çoğu gibi bu dize de 0 rakamına zorlar ve PHP karşılaştırma için true değerini döndürür.
postfuturist

8
Hızlı bir var_dump ((int) 'password123'); bunun neden olduğunu tam olarak anlamama yardımcı oldu ... ** utandım ** ... Gerçekten === operatörü
Carlton

3
bu, iki işlenenden biri sayıya dökülebilirse, '==' kullanılır, php hem işlenenleri sayılara çevirir hem de daha fazlası, sayı olmayan bir dize sayıya dökülürse, değeri sıfır alır, sonuçta sıfıra eşit olur, basit '==' ile karşılaştırmanın sonucu istenmeyen bir şey olabilir
Luca C.

98

==PHP'de kullanmayın . Beklediğinizi yapmayacak. Dizeleri dizelerle karşılaştırıyor olsanız bile, PHP bunları örtülü olarak kayar ve sayısal görünürlerse sayısal bir karşılaştırma yapar.

Örneğin '1e3' == '1000'true değerini döndürür. Bunun ===yerine kullanmalısınız .


16
Ama sadece ===.
Roman Newaza

11
@Roman evet ama bir çok PHP programcısı bunu yapmak zorunda olduklarını bilmiyorlar. Dolayısıyla uyarı.
Antimon

5
@Antimony Peki neden onlara cevabınızda ne yapmaları gerektiğini söylemiyorsunuz ?
Tim

43

Peki .. bu php hata raporuna göre , hatta 0wned alabilirsiniz.

<?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.';
    }
 ?>

Size bir uyarı verir, ancak yine de karşılaştırmayı atlayın.
Sen yapması gereken ===@postfuturist önerildiği gibi.


5
Vay canına +1. Bağlantıdan alıntı: "null döndürmek için yanlış türde argüman (lar) alan işlev için belirlenen davranış". Bu kılavuz sadece şunu söylüyor: Null bir olasılık olarak belirtilmez, ancak alt kılavuz sayfası gibi sayfalarda belirtilir. iç çekiş
Gerry

Ama aynı şey form yöntemi yazı olduğunda da olur mu?
3lokh

@NikhilGeorge Öyle, burada söz konusu işlev strcmp. Hangi girdilerin karşılaştırıldığı önemli değil.
Ajith

Hata raporu null döndürmenin iyi olduğunu söylese de bu yanlıştır. PHP 4.3'ten PHP 7.3'e kadar olan tüm resmi PHP sürümleri bu işlevlerden boş değer döndürmez. Bir alfa veya beta sürümü olabileceğinden şüpheleniyorum ve kapatılan hatanın geçersiz olmasına bakılmaksızın düzeltildi. HHVM 3.11 - 3.19'u etkilediğini gösteren ayrıntılar için bkz. 3v4l.org/Zq8tM .
Timo Tijhof

33

Dizeleri karşılaştırırken, operatörü (gevşek karşılaştırma) değil operatörü ( ===katı karşılaştırma) kullanmanız gerektiğini daima unutmayın . ==


8
Aslında, bir şeyi=== karşılaştırırken kullanmanız gerektiğini söylemek güvenli .
rink.attendant.6

22

Tüm cevapları özetliyoruz:

  • ==Bir olan kötü bir fikir dize karşılaştırmaları için.
    Birçok durumda size "şaşırtıcı" sonuçlar verecektir. Buna güvenme.

  • === gayet iyi ve size en iyi performansı verecek.

  • strcmp() genellikle sıralama işlemleri için hangi dizenin "daha büyük" olduğunu belirlemeniz gerekiyorsa kullanılmalıdır.


20

Kullanmak ==tehlikeli olabilir.

İkisi farklıysa değişkeni başka bir veri türüne atacağını unutmayın.

Örnekler:

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

Gördüğünüz gibi, bu ikisi farklı türlerden, ancak sonuç, truekodunuzun beklediği gibi olmayabilir.

Kullanılması ===, ancak biraz daha hızlı daha olduğunu Test gösterileri olarak tavsiye edilir strcmp()ve bunun küçük harf duyarsız alternatif strcasecmp().

Hızlı googling bu hız karşılaştırmasını sağlar: http://snipplr.com/view/758/


1
Bazen aynı türden olsalar bile onları farklı bir türe çevirir.
Antimon

"012" == "12"php gibi bir tamsayıyı temsil eden iki dizeyi karşılaştırırken bile her iki dizenin türünü tamsayı olarak değiştirdi 12 == 12ve sonra geri döndü true.
GoTo


6

strcmp, çalıştırdığı ortama bağlı olarak farklı değerler döndürür (Linux / Windows)!

Bunun nedeni, hata raporunun söylediği gibi bir hataya sahip olmasıdır https://bugs.php.net/bug.php?id=53999

Lütfen dikkatli davranın !!


Bununla birlikte, dizeler eşitse her zaman 0 döndürür. +1 dışında başka bir değerle ilgilenirken dikkatli olmak için +1.
Prof. Falken sözleşmesi

4

strcmp()Dizeleri sözlükbilimsel olarak sipariş etmek / karşılaştırmak istiyorsanız kullanabilirsiniz . Sadece eşitliği kontrol etmek istiyorsanız, o zaman ==gayet iyi.


1
Olduğu gibi usort . Aslında, hemen hemen sıralama için yapılmış.
Charles

@Charles Teşekkürler. Wikipedia gözlerimi parlattı.
cbednarski

1
Sıralama konusunda daha açık olmak. strcmp (), string1 string2'den önce sıralıyorsa <0, string2 string1'den önce sıralıyorsa 0 ya da aynıysa 0 değerini döndürür. Örneğin $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); aao aabo'dan önce sıralandığı için sıfırdan daha büyük dönecektir.
HTML Man

@postfuturist Eminim ki bu bir yazım hatasıdır ===.
kül

4

Ayrıca fonksiyon sıralamada yardımcı olabilir. Sıralama konusunda daha açık olmak. strcmp (), string1 string2'den önce sıralarsa 0'dan küçük, string2 string1'den önce sıralarsa 0'dan büyük veya aynıysa 0 değerini döndürür. Örneğin

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

Aao aabo'dan önce sıralama yaptığı için işlev sıfırdan daha büyük dönecektir.


0

PHP Alfabetik sıralama kullanmak yerine , karşılaştırma yapmak için karakterin ASCII değerini kullanın . Küçük harfler büyük harflerden daha yüksek ASCII değerine sahiptir. Bu tür bir karşılaştırma yapmak için === kimlik operatörünü kullanmak daha iyidir . strcmp () , ikili güvenli dize karşılaştırmaları gerçekleştirme işlevidir. İki dizeyi bağımsız değişken olarak alır ve str1 str2'den küçükse <0 döndürür; Str1 str2'den büyükse> 0 ve eşitse 0. Ayrıca, dizeleri önce küçük harfe dönüştüren ve sonra karşılaştıran strcasecmp () adında büyük / küçük harfe duyarlı olmayan bir sürüm de vardır .


0

if ($password === $password2) { ... }girişlerden birinin kullanıcı tarafından kontrol edildiği şifreler veya şifre karmaları karşılaştırılırken yapılacak güvenli bir şey değildir.
Bu durumda, bir saldırganın gerçek parola karmasını yürütme zamanı farklılıklarından türetmesine izin veren bir zamanlama kehaneti oluşturur. Bunun yerine
kullanın if (hash_equals($password, $password2)) { ... }, hash_equals "zamanlama saldırısı güvenli dize karşılaştırması" gerçekleştirir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.