try_files比if更可靠,因其是原子操作,按$uri、$uri/、/index.php?$query_string顺序检查,语义清晰无副作用;而if在location内有隐式限制,易因路径参数导致重写失效返回404。

CodeIgniter 在 Nginx 上跑不起来、访问控制器返回 404,几乎全是伪静态配置没对,不是框架问题,也不是 PHP 版本问题。
为什么 try_files 比 if (!-e $request_filename) 更可靠
Nginx 的 if 在 location 块里有隐式限制,容易触发“nested location”或变量作用域异常,尤其当请求带路径参数(如 /user/profile/123)时,if 判断可能跳过重写,直接返回 404;而 try_files 是原子操作,按顺序检查文件、目录、最后 fallback 到 /index.php,语义清晰且无副作用。
-
try_files $uri $uri/ /index.php?$query_string;是最稳妥的写法,兼容QUERY_STRING(比如带 ?page=2 这类参数) - 别用
rewrite ^/(.*)$ /index.php/$1 last;—— 它依赖 PATH_INFO,但 Nginx 默认不解析 pathinfo,需额外配fastcgi_split_path_info - 如果必须用
if(老配置迁移),确保它只出现在location /内,且last后不混用其他 rewrite
location ~ \.php($|/) 必须匹配带斜杠的 PHP 请求
CodeIgniter 的 URL 如 /user/login 实际由 index.php/user/login 处理,Nginx 需把这类请求正确转发给 PHP-FPM。若只写 location ~ \.php$,则 /index.php/user/login 中的 /user/login 会被当成路径而非脚本名,导致 404 或直接下载 PHP 文件。
- 务必用
location ~ \.php($|/)或location ~ [^/]\.php(/|$),确保能捕获index.php/xxx形式 - 必须开启
fastcgi_split_path_info并设置PATH_INFO,否则 CI 拿不到路由段:fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param PATH_INFO $fastcgi_path_info;
-
SCRIPT_FILENAME要用$document_root$fastcgi_script_name,别硬编码路径,避免部署到子目录时报错
$config['uri_protocol'] 和 $config['index_page'] 必须同步调
CI 的路由解析高度依赖这个配置。Nginx 不像 Apache 自动提供 PATH_INFO,所以不能盲目设成 'PATH_INFO' —— 它需要 Nginx 显式传参,否则会为空,导致所有路由都进默认控制器。
- 推荐先设为
'REQUEST_URI':它直接取原始 URL(如/user/login),不依赖 Nginx 传参,适配性最强 - 若坚持用
'PATH_INFO',确认 Nginx 已传PATH_INFO且值非空(可临时在index.php里var_dump($_SERVER['PATH_INFO'])验证) -
$config['index_page'] = '';必须设空,否则 URL 里会多出index.php,伪静态失效
最容易被忽略的是:Nginx 配置改完后必须 reload(nginx -s reload),不是 restart;且 PHP-FPM 缓存可能残留旧路由逻辑,建议同时重启 PHP-FPM 进程。CI 的 application/config/routes.php 里别漏掉默认路由(如 $route['default_controller'] = 'welcome';),否则即使 Nginx 转发成功,CI 层也会 404。











