PHP本身不创建虚拟目录,需通过Web服务器(如Apache/Nginx)配置URL重写规则,将请求统一转发至index.php入口文件,再由PHP解析REQUEST_URI实现路由分发,即前端控制器模式。

PHP 本身不直接创建“虚拟目录”,所谓虚拟目录通常是 Web 服务器(如 Apache 或 Nginx)的配置概念。但你可以通过 PHP 配合服务器配置,实现类似效果:让某个子路径(如 /user)不对应真实文件夹,而是统一由一个入口文件(如 index.php)接管,并在该文件中解析路由、加载逻辑——这就是典型的“前端控制器”模式(类似 Laravel、ThinkPHP 的 public/index.php)。
一、Web 服务器配置虚拟路径指向单一入口
这是关键前提。没有它,PHP 无法自动接管非物理路径的请求。
-
Apache(.htaccess 方式):确保开启
mod_rewrite,在项目根目录放 .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
这样,访问 /user/profile、/api/v1/data 等不存在的路径时,都会被重写到 index.php,而不会 404。
- Nginx(server 块内配置):
try_files $uri $uri/ /index.php?$query_string;
}
二、入口文件(index.php)获取并解析“虚拟路径”
在 index.php 中,你需要从原始请求中提取出被重写的路径(即用户看到的 URL 路径),而不是 $_SERVER['SCRIPT_NAME']。
立即学习“PHP免费学习笔记(深入)”;
- 推荐用
$_SERVER['REQUEST_URI']获取完整路径(含查询参数),再用parse_url()提取 path:
// 例如访问 /user/123?tab=info → $uri = '/user/123'
// 可选:去除前缀(如项目部署在子目录 /myapp/ 下)
$base = '/myapp'; // 根据实际调整
if (strpos($uri, $base) === 0) {
$uri = substr($uri, strlen($base));
}
$uri = trim($uri, '/'); // 得到 'user/123'
// 拆成路由段
$pathParts = explode('/', $uri); // ['user', '123']
之后你就可以根据 $pathParts 实现路由分发,比如 user 对应用户模块,123 是 ID。
三、设置默认首页(当访问虚拟目录根时自动加载 index)
如果用户访问 /user/(结尾带斜杠),你希望它等价于 /user/index,这需在入口逻辑中约定处理,而非靠服务器自动找 index.php(因为 /user/ 是虚拟的,无真实目录)。
- 在
index.php解析路径后判断:
// 主页或根路径,加载首页逻辑
require 'controller/home.php';
} elseif ($pathParts[0] === 'user' && (count($pathParts) === 1 || $pathParts[1] === 'index')) {
// /user 或 /user/index → 加载用户首页
require 'controller/user/home.php';
} else {
// 其他路由...
}
也可封装为简单规则:若最后一段为空或为 index,则忽略;例如 ['user', ''] 或 ['user', 'index'] 都视为 user 的默认行为。
四、注意事项与常见问题
- 静态资源(CSS/JS/图片)别被重写:确保
RewriteCond或try_files已排除真实存在的文件和目录,否则/css/app.css也会进 index.php 导致 500 或空白。 - URL 中文或特殊字符需
urldecode()处理($_SERVER['REQUEST_URI']是原始编码,可能含 %E4%BD%A0)。 - 不要依赖
$_SERVER['PATH_INFO']—— 它在 CGI/FastCGI 下常为空或不可靠,REQUEST_URI更通用。 - 开发时可加一句
error_log("Route: {$uri}");快速验证重写是否生效。



















