So sánh chuỗi bằng '==' so với 'strcmp ()'


334

Có vẻ như ===toán tử của PHP phân biệt chữ hoa chữ thường. Vì vậy, có một lý do để sử dụng strcmp()?

Có an toàn để làm một cái gì đó như sau?

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

10
Trường hợp nhạy cảm phải làm gì với strcmp?
kennytm

1
@KennyTM: phân strcmpbiệt chữ hoa chữ thường. Trong một số ngôn ngữ, như VB, so sánh chuỗi có thể không được, và do đó sẽ trả về một kết quả khác. Đây không phải là trường hợp trong PHP.
cHao

13
@jie: Bạn có thể muốn sử dụng ===thay ==vì vì '0XAB' == '0xab'nó là sự thật.
kennytm

17
sử dụng === thay vì == rất quan trọng, bởi vì so sánh bất kỳ chuỗi nào với 0 với == sẽ trả về true, điều này rõ ràng là sai ...
Karl Adler

4
@Kenny Ngoài ra '0xAB' == '171'
Antimon

Câu trả lời:


329

Lý do để sử dụng nó là vì strcmp

trả về <0 nếu str1 nhỏ hơn str2; > 0 nếu str1 lớn hơn str2 và 0 nếu chúng bằng nhau.

===chỉ trả về truehoặc false, nó không cho bạn biết chuỗi nào "lớn hơn".


9
icic tho trong trường hợp hiện tại của tôi, tôi không cần biết chuỗi nào lớn hơn :)
Jiew Meng

154
strcmp với chuỗi phù hợp với mất 0.207852 giây strcmp với chuỗi không phù hợp mất 0.215276 giây === với chuỗi phù hợp với mất 0.067122 giây === với chuỗi không phù hợp mất 0.057305 giây snipplr.com/view/758

3
Cách sử dụng khác cho strcmp nó hiển thị sắp xếp. Để rõ ràng hơn về sắp xếp. strcmp () trả về <0 nếu chuỗi1 sắp xếp trước chuỗi2,> 0 nếu chuỗi2 sắp xếp trước chuỗi1 hoặc 0 nếu chúng giống nhau. Ví dụ: $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); sẽ trả về lớn hơn 0, vì aaao đang sắp xếp trước aabo.
Người đàn ông HTML

20
Tại sao câu trả lời này nhận được nhiều sự ủng hộ nhất? Tôi đang từ chối vì mặc dù đó là câu trả lời mà câu hỏi này xứng đáng nhưng không phải là câu trả lời 'đúng'. Câu trả lời đúng phải là 'Sử dụng ===' vì nhiều người đã nói trong các câu trả lời khác.
onur güngor

2
@onur güngor Trên thực tế, điều này không trả lời câu hỏi của op So is there any reason to use strcmp() ?, trong khi câu trả lời của Postfuturist thì không. Oh, địa ngục ... không có một câu trả lời dường như biên dịch cùng một lúc các sử dụng của strcmp()thì hiệu suất của ===, và độ tin cậy xấu của ==để so sánh chuỗi ... vì vậy tôi thêm tôi vào danh sách.
Balmipour

222

Bạn không bao giờ nên sử dụng ==để so sánh chuỗi. ===không sao

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

Chỉ cần chạy mã trên và bạn sẽ thấy lý do tại sao.

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

Bây giờ, điều đó tốt hơn một chút.


19
== không chỉ là vấn đề đối với các loại khác nhau. Đôi khi nó sẽ cho kết quả bất ngờ ngay cả khi cả hai bên là một chuỗi. Hãy thử '1e3' == '1000'
Antimon

3
Làm thế nào 0 == 'password123'?
Andy lobel

24
@AndyLobel PHP ép buộc 'password123' thành một số bằng cách sử dụng các quy tắc so sánh lỏng lẻo của nó vì toán hạng khác là một số, chuỗi đó, giống như hầu hết, ép buộc với số 0 và PHP trả về giá trị đúng khi so sánh.
postfuturist

8
Một var_dump nhanh ((int) 'password123'); đã giúp tôi hiểu đầy đủ lý do tại sao điều này xảy ra ... ** xấu hổ ** ... Tôi thực sự thích toán tử ===
Carlton

3
đây là beacuse bằng cách sử dụng '==' nếu một trong hai toán hạng có thể chuyển thành số, php chuyển cả hai toán hạng thành số và hơn nữa, nếu một chuỗi số không được truyền thành số, nó sẽ lấy giá trị 0, kết quả bằng 0, do đó, kết quả của việc so sánh với đơn giản '==' có thể là điều không mong muốn
Luca C.

98

Đừng sử dụng ==trong PHP. Nó sẽ không làm những gì bạn mong đợi. Ngay cả khi bạn đang so sánh các chuỗi với các chuỗi, PHP sẽ ngầm chuyển chúng thành các số float và thực hiện so sánh bằng số nếu chúng xuất hiện bằng số.

Ví dụ '1e3' == '1000'trả về true. Bạn nên sử dụng ===thay thế.


16
Nhưng bạn chỉ có thể ===.
Roman Newaza

11
@Roman có nhưng rất nhiều lập trình viên PHP không biết họ phải làm điều đó. Do đó cảnh báo.
Antimon

5
@Antimony Vậy tại sao không nói với họ những gì họ nên làm trong câu trả lời của bạn?
Tim

43

Chà..theo báo cáo lỗi php này , bạn thậm chí có thể nhận được 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.';
    }
 ?>

Nó cho bạn một cảnh báo, nhưng vẫn bỏ qua việc so sánh.
Bạn nên làm ===như @postfuturist đề xuất.


5
Wow +1. Trích dẫn từ liên kết: "Nó được thiết lập hành vi cho hàm nhận loại (các) đối số sai để trả về null". Thật tuyệt vời khi xem hướng dẫn sử dụng chỉ nói điều này: "Trả về <0 nếu str1 nhỏ hơn str2;> 0 nếu str1 lớn hơn str2 và 0 nếu chúng bằng nhau". Null không được đề cập đến như một khả năng, nhưng trên các trang như trang con người nó được đề cập. thở dài
Gerry

Nhưng điều tương tự có xảy ra khi phương thức biểu mẫu được đăng không ...?
3lokh

@NikhilGeorge Nó có, chức năng trong câu hỏi ở đây là strcmp. Nó không quan trọng mà đầu vào đang được so sánh với.
Ajith

Mặc dù báo cáo lỗi nói rằng trả về null là tốt, nhưng điều này không chính xác. Tất cả các bản phát hành PHP chính thức từ PHP 4.3 đến PHP 7.3 không trả về null từ các hàm này. Tôi nghi ngờ đây có thể là bản phát hành alpha hoặc beta và bất kể lỗi nào bị đóng là không hợp lệ, nó đã được sửa. Xem 3v4l.org/Zq8tM để biết chi tiết, cho thấy nó ảnh hưởng đến HHVM 3.11 - 3.19.
Timo Tijhof

33

Luôn nhớ rằng, khi so sánh các chuỗi, bạn nên sử dụng ===toán tử (so sánh nghiêm ngặt) và không phải == toán tử (so sánh lỏng lẻo).


8
Trên thực tế, tôi nghĩ thật an toàn khi nói rằng bạn nên sử dụng ===khi so sánh bất cứ điều gì .
rink.attguard.6

22

Tổng hợp tất cả các câu trả lời:

  • ==là một ý tưởng tồi cho so sánh chuỗi.
    Nó sẽ cho bạn kết quả "đáng ngạc nhiên" trong nhiều trường hợp. Đừng tin tưởng nó.

  • === là tốt, và sẽ cung cấp cho bạn hiệu suất tốt nhất.

  • strcmp() nên được sử dụng nếu bạn cần xác định chuỗi nào là "lớn hơn", thường là để sắp xếp các hoạt động.


20

Sử dụng ==có thể nguy hiểm.

Lưu ý rằng nó sẽ chuyển biến sang loại dữ liệu khác nếu hai loại khác nhau.

Ví dụ:

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

Như bạn có thể thấy, hai cái này thuộc các loại khác nhau, nhưng kết quả là true, đó có thể không phải là những gì mã của bạn sẽ mong đợi.

===Tuy nhiên, việc sử dụng được khuyến nghị vì thử nghiệm cho thấy rằng nó nhanh hơn một chút so với strcmp()và thay thế không phân biệt chữ hoa chữ thường strcasecmp().

Googling nhanh chóng hét lên so sánh tốc độ này: http://snipplr.com/view/758/


1
Đôi khi, họ chuyển chúng sang một loại khác ngay cả khi chúng đã có cùng loại.
Antimon

ngay cả khi so sánh hai chuỗi đại diện cho một số nguyên như "012" == "12"php đã thay đổi loại của cả hai chuỗi thành số nguyên 12 == 12và sau đó được trả về true.
GoTo


6

strcmp sẽ trả về các giá trị khác nhau dựa trên môi trường mà nó đang chạy (Linux / Windows)!

Lý do là nó có lỗi như báo cáo lỗi cho biết https://bugs.php.net/orms.php?id=53999

Hãy cẩn thận xử lý !! Cảm ơn bạn.


Tuy nhiên, nó sẽ luôn trả về 0 nếu các chuỗi bằng nhau. +1 vì đã cẩn thận về việc quan tâm đến bất kỳ giá trị nào khác ngoài 0.
Hợp đồng của giáo sư Falken vi phạm

4

Bạn có thể sử dụng strcmp()nếu bạn muốn đặt hàng / so sánh các chuỗi từ vựng . Nếu bạn chỉ muốn kiểm tra sự bình đẳng thì ==tốt thôi.


1
Giống như trong usort . Trong thực tế, nó được thực hiện khá nhiều để phân loại.
Charles

@Charles Cảm ơn. Wikipedia làm mắt tôi sáng lên.
cbednarski

1
Để rõ ràng hơn về sắp xếp. strcmp () trả về <0 nếu chuỗi1 sắp xếp trước chuỗi2,> 0 nếu chuỗi2 sắp xếp trước chuỗi1 hoặc 0 nếu chúng giống nhau. Ví dụ: $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); sẽ trả về lớn hơn 0, vì aaao đang sắp xếp trước aabo.
Người đàn ông HTML

@postfuturist Tôi chắc chắn đó là một lỗi đánh máy và ý họ là vậy ===.
tro

4

Ngoài ra Các chức năng có thể giúp sắp xếp. Để rõ ràng hơn về sắp xếp. strcmp () trả về ít hơn 0 nếu chuỗi1 sắp xếp trước chuỗi2, lớn hơn 0 nếu chuỗi2 sắp xếp trước chuỗi1 hoặc 0 nếu chúng giống nhau. Ví dụ

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

Hàm sẽ trả về lớn hơn 0, vì aaao đang sắp xếp trước aabo.


0

PHP Thay vì sử dụng sắp xếp theo thứ tự chữ cái, hãy sử dụng giá trị ASCII của ký tự để so sánh. Chữ thường có giá trị ASCII cao hơn chữ hoa. Tốt hơn là sử dụng toán tử nhận dạng === để thực hiện loại so sánh này. strcmp () là một hàm để thực hiện so sánh chuỗi an toàn nhị phân. Nó nhận hai chuỗi làm đối số và trả về <0 nếu str1 nhỏ hơn str2; > 0 nếu str1 lớn hơn str2 và 0 nếu chúng bằng nhau. Ngoài ra còn có một phiên bản không phân biệt chữ hoa chữ thường có tên strcasecmp () trước tiên chuyển đổi chuỗi thành chữ thường và sau đó so sánh chúng.


0

if ($password === $password2) { ... }không phải là một điều an toàn để làm khi so sánh mật khẩu hoặc băm mật khẩu trong đó một trong những đầu vào được người dùng kiểm soát.
Trong trường hợp đó, nó tạo ra một lời tiên tri thời gian cho phép kẻ tấn công lấy được mật khẩu băm thực tế từ sự khác biệt về thời gian thực hiện.
Sử dụng if (hash_equals($password, $password2)) { ... }thay thế, bởi vì hash_equals thực hiện "so sánh chuỗi an toàn tấn công thời gian".

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.