`strpos()` 返回子字符串在字符串中**首次出現的位置**(從 0 開始),區分大小寫,找不到返回 `false`。本文重點講解返回值類型陷阱、嚴格比較必要性、偏移量用法與多位元組替代方案。
int|false strpos ( string $haystack, string $needle, int $offset = 0 )
<?php
echo strpos("Hello world!", "wo"); // 6
echo strpos("Hello world!", "Wo"); // false (區分大小寫)
?>
$haystack = "needle in haystack";
$pos = strpos($haystack, "needle"); // 0 (在開頭)
// 錯誤寫法:鬆散比較
if ($pos == false) { echo "Not found"; } // 0 == false 為 true,誤判!
// 正確寫法:嚴格比較
if ($pos === false) { echo "Not found"; }
else { echo "Found at $pos"; }
鐵律:檢查 `strpos` 結果**必須使用 `=== false` 或 `!== false`**。
$str = "ababcab";
echo strpos($str, "ab", 0); // 0
echo strpos($str, "ab", 1); // 2
echo strpos($str, "ab", 3); // 5
// 找出所有位置
$positions = [];
$offset = 0;
while (($pos = strpos($str, "ab", $offset)) !== false) {
$positions[] = $pos;
$offset = $pos + 1;
}
print_r($positions); // [0, 2, 5]
`strpos` 按**字節**查找,中文關鍵字可能匹配到字符內部字節:
$str = "中文測試";
var_dump(strpos($str, "文測")); // int(3) 正確(UTF-8 下剛好字符邊界)
var_dump(strpos($str, "文")); // int(3) 正確
// 但某些字符組合可能產生誤匹配
<?php
$str = "中文測試abc";
echo mb_strpos($str, "測試", 0, 'UTF-8'); // 6 (字符索引)
echo mb_strpos($str, "abc", 0, 'UTF-8'); // 9
?>
echo stripos("Hello World", "world"); // 6
echo mb_stripos("中文測試", "測試", 0, 'UTF-8'); // 6
$str = "ababcab";
echo strrpos($str, "ab"); // 5 (最後一次出現位置)
| 場景 | 實現 |
|---|---|
| 檢查字符串是否包含關鍵字 | `strpos($str, $keyword) !== false` |
| 解析固定格式字符串(如 CSV、日誌) | 配合 `substr` 定位分隔符 |
| 模板引擎標籤解析 | 查找 `{{` `}}` 位置提取變量名 |
| 敏感詞過濾 | 遍歷詞庫 `stripos` 檢測 |
| URL 路由匹配 | 查找 `/` 位置分割段落 |
牢記「嚴格比較 `=== false`」鐵律,並根據編碼環境選擇 `mb_strpos`,能避免 99% 的 `strpos` 相關邏輯錯誤。