
strpos() 返回 false 还是 0?这是最常翻车的地方
PHP 里查子字符串,strpos() 是首选,但它返回的是位置索引,不是布尔值。如果子串恰好在开头(索引为 0),strpos() 返回 0,而 if (0) 会被当成 false,结果误判为“没找到”。
- 必须用严格比较:
=== false判断是否未找到,不能只用== false或直接放在if里 - 正确写法:
if (strpos($str, 'abc') !== false) { /* 找到了 */ } - 错误写法:
if (strpos($str, 'abc')) { /* 开头匹配时会跳过 */ } - 注意大小写:它区分大小写;要忽略大小写,用
stripos()
mb_strpos() 是中文或 UTF-8 字符串的刚需
如果你的字符串含中文、emoji 或其他多字节字符,strpos() 可能返回错位索引甚至乱码结果,因为它按字节操作,不识别 UTF-8 编码边界。
- 只要字符串可能含非 ASCII 字符(比如用户输入、数据库读出的中文),一律改用
mb_strpos() - 记得设置内部编码:
mb_internal_encoding('UTF-8'),否则部分环境可能默认 GBK,导致行为不一致 - 参数顺序和
strpos()一致,但第四个参数可指定起始字节偏移(注意:是字节偏移,不是字符偏移) - 示例:
mb_strpos($str, '你好', 0, 'UTF-8')
str_contains() 是 PHP 8.0+ 最干净的写法
PHP 8.0 起原生支持 str_contains(),语义清晰、不纠结返回值类型、自动处理编码(底层调用 mb_strpos() 当前 locale 合理时),适合新项目或已升级环境。
- 直接返回布尔值:
str_contains($str, 'test'),无需!== false判断 - 不兼容 PHP Fatal error: Uncaught Error: Call to undefined function str_contains()
- 如果需兼容旧版,可用 polyfill:
function_exists('str_contains') || function str_contains($haystack, $needle) { return mb_strpos($haystack, $needle) !== false; } - 它不支持正则,纯字面量匹配;要模糊匹配还得回
preg_match()
preg_match() 什么时候才该上?
只有需要模式匹配(比如“以数字开头+字母结尾”“邮箱格式校验”)时,才轮到 preg_match()。它比 strpos() 慢得多,且正则写错容易引发回溯灾难。
立即学习“PHP免费学习笔记(深入)”;
- 纯子串查找,别用
preg_match()—— 写~\Qabc\E~不仅难读,还慢一倍以上 - 必须转义用户输入的搜索内容:
preg_quote($user_input, '/'),否则$user_input = 'a.b+c'会导致意外交配 - 只关心“是否存在”,用
preg_match();要取全部匹配项,用preg_match_all() - 错误现象常见:
Warning: preg_match(): Compilation failed: nothing to repeat at offset X,多半是没preg_quote()
真正麻烦的从来不是“怎么写”,而是“在哪种编码、哪个 PHP 版本、面对什么来源的数据”下选对函数。比如一个从 MySQL utf8mb4 字段读出的字符串,在 PHP 7.4 环境里用 strpos() 查中文,大概率静默失败——这种细节不盯住,线上就只能靠日志猜。











