PHP switch 默认穿透,必须显式用 break/return/throw 终止;空 case 可省略 break,但含可执行语句时必须中断;推荐统一加 break 或改用 PHP 8+ 的 match 表达式杜绝穿透风险。

PHP 中 switch 语句默认穿透,不写 break 就会继续执行下一个 case,这不是语法错误,但极大概率是逻辑 Bug。
每个非空 case 必须显式终止流程
PHP 不会自动在 case 结束时跳出,它只看有没有 break、return、throw 或函数自然结束。空 case(比如只注释或什么都没写)可以不加 break,但只要里面有一行可执行语句,就必须主动中断。
- 推荐统一用
break,除非你明确需要穿透且已加注释 - 函数内可用
return替代break,更彻底,也避免漏写 - 不要依赖
default位置来“兜底”——如果它不在最后,后面没break同样会穿透
真要穿透时必须加 // fall through 注释
多个 case 共享同一段逻辑(比如 case '4': case '6': case '9': case '11': 都输出 30 天),这是合理穿透,但必须让后续维护者一眼看懂意图。
创建并切换AI助手人格。使用 /personality 列出并激活已保存的人格;使用 /create-personality 设计新角色,自动填充 SOUL 与 IDENTITY。跨会话和对话压缩时人格持久化,自动恢复心跳。原子切换提供备份与回滚保护,切换前始终备份当前状态。
- 注释必须紧贴
case下一行或同一行末尾,如:case '4': // fall through - PHPStan、Psalm 等静态分析工具能识别这个注释,忽略该处警告;没注释则报错
- CI 流程中加入
phpstan analyse --level=5可提前拦截无注释的穿透
PHP 8+ 优先用 match 表达式替代 switch
match 是 PHP 8 引入的严格版分支语法,从设计上就杜绝了穿透问题:它不接受 break,也不允许隐式穿透,每个分支必须有返回值,未匹配会抛 UnhandledMatchError。
- 简单值匹配场景直接替换:
match ($status) { 200 => 'OK', 404 => 'Not Found' }; - 不能写
echo这类无返回语句,强制你把逻辑收束为表达式 - 类型更安全,默认严格比较,不会把字符串
"1"当成整数1匹配
松散比较 + 穿透 = 隐形雪崩
PHP switch 默认用 == 比较,这意味着 case 0: 会意外匹配 false、''、null,如果再没 break,这些本不该进来的值就会一路穿透执行后续所有分支。
- 关键业务中,改用
===的唯一可靠方式是换match,或手动转类型:case (int)$input: - 永远不要在
case值里写函数调用或表达式,如case $x > 10:是语法错误 -
default不是可选项——漏掉它,不匹配的输入就静默跳过,连日志都没有
穿透本身不是缺陷,是语言特性;但人脑记不住哪些地方该穿透、哪些不该,所以最稳妥的做法是:默认都加 break,真要穿透就加注释,新项目直接用 match。

















