在PHP网站开发中,我们经常会遇到网站部署在服务器子目录下的情况,比如把项目放在/blog/目录,用户访问时需要输入domain.com/blog/index.php才能打开首页,体验不够友好。通过前端控制器配合URL重写规则,就可以让子目录下的内容伪装成根目录直接访问,用户只需要输入domain.com/index.php就能访问到子目录中的内容。

核心实现原理
整个方案的核心分为两部分,第一是前端控制器,所有请求都先转发到子目录下的统一入口文件处理;第二是URL重写规则,把根目录的请求映射到子目录的对应资源,同时隐藏真实的子目录路径。
前端控制器的作用
前端控制器是一个统一的入口文件,通常命名为index.php,所有用户请求都会先经过这个文件,再由它根据请求路径分发到对应的业务逻辑。在子目录伪根的场景中,前端控制器需要放在子目录内,负责接收重写后的请求并处理。
URL重写的作用
URL重写是通过服务器配置,把用户访问的根目录请求,在服务器内部转发到子目录的对应资源,同时不改变用户浏览器地址栏的显示,让用户感知不到真实的子目录路径。
Apache服务器配置步骤
如果使用的是Apache服务器,需要先确保开启了mod_rewrite模块,然后在网站根目录创建.htaccess文件,添加以下重写规则:
# 开启重写引擎
RewriteEngine On
# 如果请求的不是真实存在的文件或目录,就转发到子目录的入口文件
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 这里假设子目录是blog,根据实际情况修改
RewriteRule ^(.*)$ /blog/index.php?$1 [L,QSA]同时子目录/blog/下也需要创建.htaccess文件,避免子目录内的重写规则冲突:
RewriteEngine On
# 禁止子目录内的规则再次重写请求
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]Nginx服务器配置步骤
如果使用Nginx服务器,需要修改对应的站点配置文件,在server块中添加以下重写规则:
location / {
# 尝试访问真实文件,不存在则转发到子目录的入口文件
try_files $uri $uri/ /blog/index.php?$args;
}
# 处理PHP文件的解析
location ~ \.php$ {
# 这里假设子目录是blog,根据实际情况修改
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 如果是子目录的请求,调整脚本路径
if ($fastcgi_script_name ~ ^/blog/(.*)$) {
set $real_script_name /$1;
}
if ($real_script_name) {
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
}
}前端控制器示例代码
子目录/blog/下的index.php作为前端控制器,示例代码如下:
<?php
// 获取请求路径,去除前后的斜杠
$requestUri = trim($_SERVER['REQUEST_URI'], '/');
// 如果是根目录请求,默认访问首页
if (empty($requestUri)) {
$requestUri = 'home';
}
// 简单路由逻辑,根据请求路径加载对应页面
$pageMap = [
'home' => 'home.php',
'about' => 'about.php',
'contact' => 'contact.php'
];
if (array_key_exists($requestUri, $pageMap)) {
$pageFile = __DIR__ . '/' . $pageMap[$requestUri];
if (file_exists($pageFile)) {
require $pageFile;
} else {
echo '页面不存在';
}
} else {
echo '404 页面未找到';
}
?>注意事项
- 修改服务器配置后需要重启对应服务,Apache执行
service apache2 restart,Nginx执行service nginx restart让配置生效。 - 如果网站中有静态资源(如CSS、JS、图片),需要确保重写规则不会拦截这些资源的请求,上面的规则中已经通过
RewriteCond %{REQUEST_FILENAME} !-f排除了真实存在的文件。 - 如果子目录名称需要修改,要同时更新服务器重写规则和前端控制器中的路径配置,避免路径不匹配导致访问异常。
- 开发环境中可以先开启服务器重写日志,方便排查规则不生效的问题,生产环境建议关闭日志避免性能损耗。