PHP_SAPI失效时应通过REQUEST_METHOD和SCRIPT_FILENAME组合验证Web环境,辅以HTTP字段、getallheaders、STDIN流检测及argv校验,最终封装为可降级的detect_runtime_mode函数。

PHP_SAPI 失效属于极小概率事件(如 PHP 编译时未定义该常量、老旧版本或异常嵌入环境),但一旦发生,不能直接放弃判断——此时应转向 $_SERVER 中多个稳定字段的组合验证,而非依赖单一键名。核心思路是:Web 环境必然携带 HTTP 协议上下文痕迹,CLI 环境则天然缺失这些字段,且具备可识别的执行特征。
优先检查 REQUEST_METHOD 和 SCRIPT_FILENAME 关系
这两个字段在所有标准 Web SAPI(fpm-fcgi、apache2handler、litespeed、cgi-fcgi)中均被可靠注入,且 CLI 下始终不存在或为空:
-
isset($_SERVER['REQUEST_METHOD']) && !empty($_SERVER['REQUEST_METHOD'])—— Web 请求必有方法(GET/POST/PUT等),CLI 下该键通常未定义或为空字符串 -
isset($_SERVER['SCRIPT_FILENAME']) && file_exists($_SERVER['SCRIPT_FILENAME'])—— Web 模式下该值指向被请求的 PHP 脚本真实路径;CLI 下虽可能被设置(如通过 -f 参数),但多数场景为空或非法路径 - 二者同时成立,基本可确认为 Web 环境;若任一不满足,再进入下一步验证
辅助验证 HTTP 相关字段与输入流状态
单靠一个字段易误判,需交叉印证:
- 检查
$_SERVER['HTTP_HOST']或$_SERVER['REMOTE_ADDR']是否存在且非空 —— CGI/FastCGI 下可能缺失,但搭配 REQUEST_METHOD 使用可提升置信度 - 尝试调用
function_exists('getallheaders') && getallheaders()—— 若返回非空数组,100% 是 Web 环境;若函数不存在或返回空,则不否定,仅作旁证 - 检测
stream_get_meta_data(STDIN)中的wrapper_type:CLI 下通常为plainfile或STDIO;Web 下多为php://input或不可读流,但此法需配合其他项使用,不宜单独采信
CLI 的强证据链:argv + 执行上下文校验
当 Web 特征全部缺失时,仍需排除“伪 CLI”(如被 Web 脚本 include 的 CLI 工具):
- 确认
isset($_SERVER['argv']) && is_array($_SERVER['argv']) && count($_SERVER['argv']) >= 1 - 进一步比对
$_SERVER['argv'][0]是否为真实脚本路径(可用realpath($_SERVER['argv'][0]) === realpath(__FILE__)判断是否为主入口) - 若两者一致,且无任何 REQUEST_METHOD / HTTP_* 字段,则可安全认定为 CLI 主进程
兜底策略:避免硬编码,封装可维护判断函数
不要散列判断逻辑。建议统一封装:
function detect_runtime_mode(): string
{
if (defined('PHP_SAPI') && PHP_SAPI !== '') {
return PHP_SAPI;
}
<pre class="brush:php;toolbar:false;">if (isset($_SERVER['REQUEST_METHOD']) && !empty($_SERVER['REQUEST_METHOD'])) {
return 'web';
}
if (isset($_SERVER['argv']) && is_array($_SERVER['argv']) &&
!empty($_SERVER['argv']) &&
realpath($_SERVER['argv'][0] ?? '') === realpath(__FILE__)) {
return 'cli';
}
// 最终 fallback:根据常见 SAPI 字符串推测(仅作日志或调试用,不用于关键分支)
$sapi = php_sapi_name() ?: 'unknown';
return str_starts_with($sapi, 'cli') ? 'cli' : ($sapi === 'cgi-fcgi' || $sapi === 'fpm-fcgi' ? 'web' : 'unknown');}
该函数在 PHP_SAPI 不可用时自动降级,兼顾可靠性与可读性,也便于后续扩展容器或 Serverless 环境适配。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











