最稳妥的方式是用str_starts_with(php_sapi, 'cli')判断cli或类cli环境,覆盖'cli'和'cli-server'等变体;web环境应基于白名单in_array(php_sapi, ['fpm-fcgi','apache2handler','cgi-fcgi','litespeed'], true)确认,避免误判phpdbg、embed等非web场景。

最稳妥的方式是用 PHP_SAPI 常量做前缀判断,而不是简单比对是否等于 'cli'。因为真实环境中会出现 'cli-server'、'phpdbg'、'embed' 等非 Web 类型 SAPI,它们虽不属标准 CLI,但也不该归入 Web 流程。
为什么不能直接写 PHP_SAPI === 'cli'
硬匹配会漏掉开发服务器(php -S)、调试器(phpdbg)或嵌入式调用场景。这些环境没有 HTTP 请求上下文,却可能被误判为 Web,导致 session 初始化、header 输出等操作失败。
-
cli-server是 PHP 内置服务器,属于 CLI 衍生,但处理 HTTP 请求 -
phpdbg和embed明确非 Web,但也不支持 $_SERVER['REQUEST_METHOD'] - 只靠
=== 'cli'会让 Laravel 的serve命令或 PHPUnit 的调试运行出问题
推荐的 Web/CLI 分界逻辑
Web 模式应基于“已知 Web SAPI 白名单”确认,其余视为非 Web(含 CLI 及其变体):
- 判断 Web:用
in_array(PHP_SAPI, ['fpm-fcgi', 'apache2handler', 'cgi-fcgi', 'litespeed'], true) - 判断 CLI 或类 CLI:用
str_starts_with(PHP_SAPI, 'cli')(覆盖'cli'和'cli-server') - 避免反向排除:不要写
!str_starts_with(PHP_SAPI, 'cli')就认定是 Web,因为'phpdbg'也会进这个分支
增强健壮性的兜底写法
在框架启动早期或配置加载阶段,可能遇到常量未定义的情况(极老版本或特殊编译),建议加一层降级:
- 先检查
defined('PHP_SAPI'),未定义则调用php_sapi_name() - 再统一用
str_starts_with()或白名单in_array()判断 - 不依赖
$_SERVER['argv']或$_SERVER['HTTP_HOST'],它们在容器、FastCGI 或 include 场景下极易伪造或缺失
实际应用中的关键细节
区分模式不只是为了 echo 一句提示,而是影响路径构建、输入读取、日志级别和扩展行为:
- CLI 下应使用
__DIR__构建绝对路径,避免相对路径在 cron 中失效 - Web 下可安全调用
session_start(),CLI 下必须跳过或改用文件/Redis 存储 -
getallheaders()在 CLI 下会警告,Web 下也可能不可用(如 CGI),不能作为 Web 判定依据 - 同一份代码在
php -S和php artisan serve中都走cli-server,需额外检查是否有$_SERVER['REQUEST_URI']来决定是否启用路由
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











