根本原因是nginx默认不解析path_info,需通过fastcgi_split_path_info正则切分uri,并配合php.ini中cgi.fix_pathinfo=1、正确location匹配规则及框架uri协议配置为path_info才能生效。

为什么 PATH_INFO 在 Nginx 下总是为空?
根本原因不是 CodeIgniter 配置错了,而是 Nginx 默认不解析 PATH_INFO —— 它把 /index.php/welcome/test 当作整个脚本路径,没把 /welcome/test 拆出来传给 PHP。
必须靠 fastcgi_split_path_info 手动切分,且正则必须匹配到“真实 PHP 文件名 + 后续路径”两段。常见错误是正则写成 ^(.+\.php)(.*)$,但实际请求可能是 /index.php//welcome/test(双斜杠)或带查询参数,导致切分失败。
-
fastcgi_split_path_info的正则要加非贪婪修饰符:^(.+?\.php)(/.*)$,否则在嵌套路径(如/admin/index.php/api/v1/users)下会多截一段 - 务必检查
fastcgi_params文件里是否已定义了PATH_INFO—— 如果有,你后写的fastcgi_param PATH_INFO $fastcgi_path_info会被覆盖,必须注释掉原行 - PHP 端需确认
cgi.fix_pathinfo=1(php.ini 中),设为 0 会直接忽略 PATH_INFO
location ~ \.php($|/) 中的 $ 和 / 到底要不要?
要,而且顺序不能错。写成 \.php($|/) 是为了同时匹配 .php 结尾和 .php/xxx 形式,这是 Pathinfo 路由的前提。漏掉 $ 会导致 .php5 或 .phps 也被误判;漏掉 / 则无法捕获 /index.php/welcome 这类请求。
更关键的是:这个正则不能写成 \.php$(只认结尾),也不能写成 \.php(无边界,易误匹配)。
- 推荐写法:
location ~ [^/]\.php($|/),避免匹配到/static/js/app.php.min这类伪 PHP 资源 - 如果用
try_files做 fallback,location /块里不要重复写rewrite,否则和location ~ \.php冲突 - 测试时用
curl -I http://yoursite/index.php/welcome/test,看响应头中X-Powered-By是否出现,再查 PHP 日志里的$_SERVER['PATH_INFO']值
try_files 和 rewrite 哪个更适合 CI 的 URL 重写?
try_files 更稳,rewrite 更灵活但容易循环。CI 的典型需求是“所有非静态资源都交给 index.php 处理”,try_files $uri $uri/ /index.php?$query_string 一行就搞定,不用担心正则写错导致 500 或无限重定向。
但注意:try_files 本身不传递 PATH_INFO,它只做路由转发;PATH_INFO 解析仍依赖 fastcgi_split_path_info 在 PHP 处理块里完成。
- 若坚持用
rewrite,必须加last标志,且放在location /块末尾,否则可能被后续location ~ \.php二次拦截 -
if (!-e $request_filename) { rewrite ... }是反模式 —— Nginx 官方明确不推荐在server或location级别用if做文件存在判断,性能差且行为不可预测 - CI4 若用
public/入口,root必须指向public/目录,try_files的 fallback 路径也要对应写成/index.php?$query_string(不是/public/index.php)
配置生效后还是 404 或跳回 index.php?
大概率是浏览器缓存了旧的 302 重定向,尤其是 Chrome 对带 index.php 的 URL 有强缓存策略。清空浏览器缓存或换隐身窗口测试,比改十次 Nginx 配置都管用。
另一个隐蔽问题是 $config['uri_protocol'] 设成了 "AUTO" —— 它在 Nginx 下常 fallback 到 QUERY_STRING,导致 PATH_INFO 被忽略。必须显式设为 "PATH_INFO"。
- CI3:改
application/config/config.php中的$config['uri_protocol'] = "PATH_INFO"; - CI4:改
app/Config/App.php中的$uriProtocol = 'PATH_INFO';,同时确认$indexPage = ''; - 验证方式:在控制器里加
var_dump($_SERVER['PATH_INFO'], $_SERVER['REQUEST_URI']);,正常应看到类似/welcome/test和/index.php/welcome/test
PATH_INFO 支持本质是 Nginx 和 PHP 协同切分 URI 的结果,任何一环断开(正则、参数覆盖、php.ini 设置、框架配置)都会让整条链路失效,排查时得逐层打点,不能只盯 Nginx 配置。











