必须同时满足三个条件:mod_rewrite已启用、AllowOverride All已设置、.htaccess位置正确(CI3在根目录,CI4在public/),否则重写不生效,框架收不到请求,路由配置无效。

改了 $config['index_page'] = '' 却还是跳转到 /index.php/about?这不是路由写错了,是重写根本没生效——框架连请求都没收到。
Apache下.htaccess不生效的三个硬性条件
CodeIgniter 的 URL 重写依赖 Apache 把所有非静态资源请求转发给 index.php,否则路由层压根不会启动。必须同时满足:
-
mod_rewrite已启用(phpinfo()查Loaded Modules是否含rewrite_module) - 对应目录的 Apache 配置中
AllowOverride All已设置(不能是None或FileInfo) -
.htaccess文件放在正确位置:CI3 在项目根目录(与index.php同级),CI4 必须在public/目录下
常见错觉是“文件一放就通”,其实 Apache 压根不读它,后面所有配置都是白忙。
CI3 和 CI4 的 .htaccess 写法不能混用
入口文件路径不同,重写目标必须严格匹配,否则 $_SERVER['PATH_INFO'] 解析错位,路由全崩:
- CI3 标准写法(
.htaccess放根目录):RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L] - CI4 标准写法(
.htaccess放public/):RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L]
CI4 若把 .htaccess 错放到根目录,或没改 app/Config/App.php 中的 $indexPage = '',都会导致 404 或无限重定向。
$route 规则匹配失败的典型写法
CI 路由按数组顺序逐条匹配,且是前缀式字符串匹配,不是正则全量匹配。以下写法极易失效:
-
$route['catalog/product/(:any)'] = 'catalog/view/$1';—— 缺少结尾/或$,可能被更宽泛的规则吞掉 -
$route['backend/user/profile/(:num)/'] = 'backend/user/profile/$1';—— 实际 URL 是/backend/user/profile/204/disabled,后半段直接丢弃 - 直接用中文、空格、点号写 key:
$route['关于我们'] = 'home/about';—— Apache 可能提前返回 400,CI 根本收不到请求 - 试图用
$route匹配查询参数:$route['search?keyword=cat']——$route不处理$_GET,那是控制器自己该干的事
真正安全的写法是纯 ASCII 字符 + (:any)/(:num) 占位符,并确保目标控制器方法存在、可访问。
Nginx 用户别碰 .htaccess
Nginx 不识别 .htaccess,硬塞进去只会报错或静默失效。必须在 server 块中显式配置:
- 推荐写法(兼容尾部斜杠):
location / { try_files $uri $uri/ /index.php?$query_string; } - 若用 PATH_INFO 模式(需同步设
$config['uri_protocol'] = 'PATH_INFO'):location ~ \.php($|/) { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } if (!-e $request_filename) { rewrite ^/(.*)$ /index.php/$1 last; }
最常被忽略的是:Nginx 配置修改后必须 nginx -t && systemctl reload nginx,否则规则永远不生效。


















