2014年7月14日 星期一

PHP 比對非0字串與整數0時卻回傳true問題

今天強者我朋友遇到PHP比對字串和0時卻發生回傳結果不如預期的問題,因為還挺有趣的所以就筆記下來

以下用簡單的switch case程式碼說明
<?php
$foo = 0;
switch ($foo)
{
    case "str1":
        echo "str1";
        break;
    case "str2":
        echo "str2";
        break;
    default:
        echo "default";
}
?>
Result
str1
由於直覺上0不可能等於"str1"應該要印出"default"才合理,為此筆者翻了一下PHP的文件Comparison Operators,其中有一句話這麼說

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. These rules also apply to the switch statement.

簡單翻譯:
   若用"=="比對的是數字和字串時,字串會被轉換為數字再進行比對,此規則也適用於switch-case

因此上述的switch-case程式碼實際比對的流程如下
  1. 由於比對的是整數和字串,因此準備開始轉換字串"str1"為整數
  2. 無法將字串由"str1"轉換為整數,因此PHP將字串"str1"轉換為0
  3. 由於"str1"轉換為0且$foo也為0,因此PHP判斷條件式case "str1"成立印出"str1"到網頁上

同樣的問題可以簡化為
<?php
echo (0 == "str1" ? "true" : "false") . "<br />";
var_dump((int)"str1");
?>
Result
true // 0等於"str1" int(0) // 整數型態的0
顯然地,要比對字串和數字時千萬要小心,不然就是用"==="來進行比對避免出問題
那若我們比對的是0和"1str"呢?
<?php
echo (0 == "1str" ? "true" : "false") . "<br />";
echo (1 == "1str" ? "true" : "false") . "<br />";
var_dump((int)"1str");
?>
Result
false // 0不等於"1str" true // 1等於"1str" int(1) // 整數型態的1 至於為啥會有這樣的結果呢?不要懷疑,就只是PHP的規則如此而已XD

參考資料
1. Comparison Operators

沒有留言:

張貼留言