PHP 提供多種字串比較函數,行為差異常導致邏輯錯誤。本文系統整理 ==/===、strcmp 系列、strnatcmp 自然排序比較的規則、回傳值含義與適用場景。
| 運算子 | 比較類型 | 規則 | 範例 |
|---|---|---|---|
== | 鬆散比較 | 型別轉換後值相等 | 22 == "22" → true |
=== | 嚴格比較 | 型別與值皆相同 | 22 === "22" → false |
!=/<> | 鬆散不等 | 同上 | |
!== | 嚴格不等 | 同上 |
建議: 預設使用 ===/!==,避免隱性型別轉換導致的驚喜(如 "0e123" == "0e456" 為 true,科學記號法比較)。
回傳值規則: <0(前<後)、0(相等)、>0(前>後)。
strcmp("abcdd", "abcde"); // 1 >0,比較到 'd' vs 'e',d後
// 修正:strcmp 逐字元比較 ASCII 碼
// 'd'(100) vs 'e'(101) -> 100-101 = -1 <0,表示前<後
// 實際執行:strcmp("abcdd","abcde") 回傳 -1
strcasecmp("abcdd", "abcde"); // -1,同 strcmp 但先轉同大小寫
strcasecmp("ABC", "abc"); // 0
strncmp("abcdd", "abcde", 3); // 0,僅比較前 3 字元 "abc"
strncasecmp("AbCdd", "aBcde", 3); // 0
解決「10.gif < 5.gif」的字典序問題,按人類直覺比較數字大小。
strcmp("10.gif", "5.gif"); // -1(字典序 '1' < '5')
strnatcmp("10.gif", "5.gif"); // 1 (自然序 10 > 5)
strnatcasecmp("10.GIF", "5.gif"); // 1
適用場景: 檔案名排序、版本號比較(v1.10 > v1.2)、含數字的 ID 排序。
| 函數 | 大小寫 | 比較範圍 | 典型用途 |
|---|---|---|---|
strcmp | 敏感 | 全字串 | 一般字串相等/排序 |
strcasecmp | 不敏感 | 全字串 | 用戶輸入、域名、Email 比對 |
strncmp | 敏感 | 前 n 字元 | 前綴匹配、協議頭檢查 |
strncasecmp | 不敏感 | 前 n 字元 | 同上,忽略大小寫 |
strnatcmp | 敏感 | 全字串 | 檔案名、版本號自然排序 |
strnatcasecmp | 不敏感 | 全字串 | 同上,忽略大小寫 |
$versions = ['v1.2', 'v1.10', 'v1.1', 'v2.0', 'v1.3'];
usort($versions, function($a, $b) {
// 移除 'v' 前綴再自然比較
return strnatcmp(substr($a,1), substr($b,1));
});
print_r($versions);
/*
Array
(
[0] => v1.1
[1] => v1.2
[2] => v1.3
[3] => v1.10
[4] => v2.0
)
*/
if (strcmp($a,$b)) 判斷相等,必須 === 0。mb_strcmp(需 mbstring 擴展)或轉碼後比較。== 陷阱: "00" == "0" 為 true,"0e123" == "0e456" 為 true(科學記號)。永遠用 === 或 strcmp。字串比較看似簡單,實則暗藏型別轉換、編碼、自然序等陷阱。記住:嚴格相等用 ===,排序/大小比較用 strcmp 系列,含數字自然排序用 strnatcmp,並留意多位元組場景補充 mb_* 函數。