CodeIgniter在Nginx下404或参数丢失,主因是uri_protocol设为PATH_INFO但Nginx未正确传递PATH_INFO;需配置fastcgi_split_path_info、try_files及fastcgi_param PATH_INFO,并确保Pagination启用query_string_segment。

CodeIgniter 在 Nginx 上跑不起来,八成不是框架问题,而是 uri_protocol 和 Nginx 重写规则没对上。默认用 Apache 的配置直接扔进 Nginx,必然 404 或无限跳转。
为什么 CodeIgniter 的 URL 在 Nginx 下全 404
根本原因是 Nginx 不像 Apache 自带 .htaccess 支持,CI 的路由依赖 PATH_INFO 或查询字符串提取控制器/方法,而 Nginx 默认不传递原始路径给 index.php。
常见错误现象:
- 访问
/user/profile返回 404,但/index.php/user/profile能通 - 分页链接生成为
/user/list?per_page=10,但点击后变成/user/list且参数丢失 -
$this->input->get()拿不到路由段,$this->uri->segment()全为空
必须同时满足两个条件:
-
application/config/config.php中设$config['uri_protocol'] = 'PATH_INFO'; - Nginx 配置中用
try_files把所有非静态请求兜底到/index.php,并确保fastcgi_param正确传递PATH_INFO
别碰 REQUEST_URI 或 QUERY_STRING 模式——它们在 Nginx 下容易被截断或双重编码,尤其带中文或特殊符号时。
最简可靠的 Nginx 配置(支持 PATH_INFO)
这段配置经过 CI 4.4+ 和 PHP 8.2 实测,不依赖 rewrite 指令,避免正则误匹配:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
}
关键点说明:
-
fastcgi_split_path_info必须存在,否则$fastcgi_path_info为空 →PATH_INFO传不进去 → CI 解析失败 -
try_files后的$query_string保留原始 GET 参数,分页、搜索等依赖它 - 不要加
if (!-e $request_filename)—— 它和try_files冲突,Nginx 官方已明确弃用if做文件存在判断
分页参数丢失的修复方案
CI 的 Pagination 类在 PATH_INFO 模式下,默认把分页参数塞进查询字符串,但 Nginx 配置若没透传 $query_string,就会丢掉 per_page。
两处必须检查:
- 控制器里初始化分页时,显式指定
query_string_segment:$config['query_string_segment'] = 'per_page'; - 生成链接时,确保 base_url 包含问号,让 CI 把参数拼在后面:
$config['base_url'] = site_url('user/list?');(注意结尾的?)
如果硬要走 PATH_INFO 分页(如 /user/list/10),就得改写 Pagination 类的 _get_pagination_number() 方法,从 URI 段取值而非 GET —— 但 CI 官方不推荐,升级时易覆盖。
缓存与并发优化的实际阈值
这些配置不是“开了就快”,而是有明确物理边界:
-
worker_connections 102400需配合系统级限制:运行ulimit -n查当前值,若低于 65536,必须改/etc/security/limits.conf,否则 Nginx 启动报socket() failed (24: Too many open files) -
gzip_comp_level 2是平衡点:level 1 压缩率低,level 6+ CPU 占用翻倍但体积只省 5%~8%,对 CI 这类动态 HTML 效果有限 - 数据库查询缓存(
$db['default']['cache_on'] = TRUE)只对完全相同的 SQL 生效,带变量的WHERE id = ?不命中 —— 别指望它加速用户个性化页面
真正卡住高并发的,往往是会话存储。文件型会话在 200+ 并发时就可能锁死,换成 Redis 驱动前,先确认 $config['sess_driver'] = 'redis' 且 $config['sess_save_path'] = 'tcp://127.0.0.1:6379?database=1' —— 少一个问号或端口错位,CI 就静默退化回文件存储。


















