php中strpos找不到子串返回false而非-1,需用!== false严格判断;处理中文等多字节字符必须用mb_strpos等函数并显式指定'utf-8'编码。

strpos 找不到字符串时返回 false,不是 -1
PHP 的 strpos 函数查不到子串时返回 false,不是其他语言常见的 -1。直接用 == 判断会出错,因为 0 == false 成立——开头就匹配到,反而被当成“没找到”。
- 必须用严格比较:
=== false或!== false - 如果要兼容 0 起始位置,别写
if (strpos($str, 'a')) { ... } -
stripos行为一致,只是忽略大小写
if (strpos($text, 'key') !== false) {
echo '找到了';
}mb_strpos 处理中文等多字节字符必须显式指定编码
用 strpos 查中文、emoji 或 UTF-8 特殊符号,大概率返回错误位置或 false——它按字节算偏移,而一个中文占 3 字节,strpos 会把中间字节当独立字符切开。
- 改用
mb_strpos,但必须传第 4 个参数:'UTF-8' - 不传编码时,PHP 依赖
mb_internal_encoding(),线上环境常不一致,极易出 bug - 如果项目已设全局编码,仍建议显式传参,避免部署差异
$pos = mb_strpos($text, '你好', 0, 'UTF-8');
strrpos 和 mb_strrpos 返回最后一次出现的位置
要找末尾匹配(比如取文件扩展名、提取最后一个分隔符后内容),别循环调用 strpos,PHP 有原生支持。
-
strrpos对单字节安全,mb_strrpos对中文/emoji 安全 - 注意:它们也返回
false而非-1,同样要=== false判断 - 和
strpos不同,它们不支持起始偏移量(offset参数)
// 取最后一个点之后的内容(安全版) $dotPos = mb_strrpos($filename, '.', 0, 'UTF-8'); $ext = $dotPos !== false ? mb_substr($filename, $dotPos + 1, null, 'UTF-8') : '';
用 mb_substr 配合位置做截取时,第三个参数是长度不是结束索引
拿到位置后想截取,常见误用是把 mb_strpos 结果直接当结束位置传给 mb_substr,结果截出来为空或错位。
立即学习“PHP免费学习笔记(深入)”;
-
mb_substr($str, $start, $length, 'UTF-8')—— 第三个参数是「取多少个字符」,不是「截到哪」 - 要截取从位置 A 到位置 B(含),得算:
$length = $B - $A + 1 - 省略第三个参数会截到末尾,但记得指定编码,否则默认用内部编码,可能乱码
// 正确:取从第2个中文到第5个中文(共4个字符)
$start = mb_strpos($text, '起始', 0, 'UTF-8');
$end = mb_strpos($text, '结束', 0, 'UTF-8');
if ($start !== false && $end !== false && $end >= $start) {
$len = $end - $start + mb_strlen('结束', 'UTF-8');
$part = mb_substr($text, $start, $len, 'UTF-8');
}多字节字符串的位置操作,核心就两点:函数选对(mb_* 系列)、编码写死('UTF-8')。漏掉任意一个,测试时看着正常,上线后遇到中文或特殊符号就崩。











