codeigniter 4.7.2 子目录部署时,rewritebase 必须设为与实际访问url前缀完全一致且以斜杠结尾的路径,如项目在 https://www.php.cn/link/0f69f766b0e791190d856ab6538d34b8 则写 rewritebase /myapp/;错误写法(缺开头或结尾斜杠)会导致路由匹配失败或静态资源404;nginx下须删除该指令并改用try_files。

CodeIgniter 4.7.2 子目录部署时 .htaccess 的 RewriteBase 怎么设
子目录部署(比如项目放在 @#@#@#@#@#@#@#@#@#@0)下,RewriteBase 必须显式声明,否则 index.php 找不到请求路径,所有非首页 URL 都会 404。
RewriteBase 的值不是随便写路径名,它必须和浏览器实际访问的 URL 前缀完全一致,且以斜杠结尾。例如:
- 项目 URL 是
@#@#@#@#@#@#@#@#@#@1→RewriteBase /myapp/ - 项目 URL 是
@#@#@#@#@#@#@#@#@#@2→RewriteBase /v2/ - 项目 URL 是根目录(
/)→RewriteBase /,可省略但建议保留
常见错误:
- 写成
RewriteBase myapp(缺开头斜杠)→ Apache 忽略该指令 - 写成
RewriteBase /myapp(结尾没斜杠)→ 多数情况仍能工作,但部分重写规则(如静态资源匹配)会出错 - 在 Nginx 下误用
RewriteBase→ Nginx 完全不认这个指令,必须删掉
你的 .htaccess 应放在项目根目录(与 index.php 同级),内容类似:
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /myapp/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</ifmodule>
为什么 index.php 路径在子目录下会出错
CI4 的入口文件 public/index.php 默认假设自己位于 Web 根目录。子目录部署时,$_SERVER['SCRIPT_NAME'] 会是 /myapp/public/index.php,但框架内部用它推导 BASEPATH 和路由前缀,若没配对 RewriteBase,$request->getUri()->getPath() 可能多出 /myapp 段,导致路由匹配失败或静态资源 404。
关键点:
-
RewriteBase不影响 PHP 文件执行,只影响 Apache 对RewriteRule中相对路径的解析 - CI4 的
public/index.php本身不读取RewriteBase,但它依赖 Apache 正确重写后的REQUEST_URI - 若你改用 Nginx,必须彻底抛弃
.htaccess和RewriteBase,改用try_files并确保root指向public/目录
子目录部署时 $config['base_url'] 怎么配才不翻车
$config['base_url'] 必须和真实访问 URL 一致,且末尾带斜杠。它用于生成 asset 链接(CSS/JS/img)、重定向 URL 等,错配会导致资源加载失败或跳转到错误域名。
正确写法(在 app/Config/App.php 中):
public $baseURL = '@#@#@#@#@#@#@#@#@#@1';public $baseURL = '@#@#@#@#@#@#@#@#@#@4';
容易踩的坑:
- 写成
'/myapp/'(相对协议)→ 无法跨域,HTTPS 页面里混入 HTTP 资源会被浏览器拦截 - 写成
'@#@#@#@#@#@#@#@#@#@5'(结尾没斜杠)→base_url('css/app.css')会拼成@#@#@#@#@#@#@#@#@#@6,直接 404 - 在生产环境硬编码域名 → 推荐用
$_SERVER['HTTP_HOST']动态构造,但需校验 Host 头防污染
子目录 + 多语言路由时 $route 规则要避开哪些陷阱
子目录部署叠加多语言(如 /myapp/zh_cn/login),路由规则必须先剥离子目录前缀,再处理语言段,否则正则会匹配错位。
错误示例(在 app/Config/Routes.php 中):
-
$routes->add('^(zh_cn|en_us)/(.+)$', '$2');→ 这个正则在子目录下实际匹配的是/zh_cn/login,但REQUEST_URI是/myapp/zh_cn/login,根本不会触发
正确做法是:让 Apache 在重写阶段就去掉子目录前缀,或改用 CI4 的 setNamespace + 前缀分组:
-
在
app/Config/Routes.php中用分组:$routes->group('zh_cn', ['namespace' => 'App\Controllers\ZhCn'], function ($routes) { $routes->add('login', 'Auth::login'); }); -
或统一在入口前做一次重写(推荐):在 Apache 的 VirtualHost 中加:
RewriteRule ^/myapp/(zh_cn|en_us)/(.*)$ /myapp/$2 [L]
子目录和多语言叠加时,最易被忽略的是:CI4 的路由调试工具(php spark routes)默认不模拟子目录上下文,输出的路径是根目录视角,得手动验证真实 URL 行为。











