在现代Web开发中,尤其是在使用MVC(Model-View-Controller)或类似架构的PHP框架时,通常会将所有前端请求统一路由到一个入口文件(例如index.php),而这个入口文件通常位于项目根目录下的一个子目录(如public/)中。这样做有助于分离公共可访问资源与核心应用逻辑,提升安全性和项目结构清晰度。然而,Apache服务器的默认配置可能无法直接满足这种需求。本文将指导您如何通过mod_rewrite模块在.htaccess文件中实现这一目标。
我们的目标是实现以下行为:
mod_rewrite是Apache的一个强大模块,它允许通过正则表达式重写URL。.htaccess文件是放置在Web服务器目录中的配置文件,它为该目录及其子目录提供配置指令。要使用mod_rewrite,请确保您的Apache服务器已启用此模块,并且在httpd.conf或虚拟主机配置中,相关目录的AllowOverride指令设置为All或至少包含FileInfo。
为了满足上述需求,我们将在项目的根目录(即包含public/目录的上一级目录)创建一个.htaccess文件。以下是推荐的.htaccess配置内容:
# 启用RewriteEngine
RewriteEngine On
# 设置RewriteBase,指定重写规则的基准URL路径
# 如果您的网站部署在子目录中(例如 http://localhost/myproject/),则应设置为 /myproject/
RewriteBase /
# 规则1: 检查请求是否指向一个真实存在的文件或目录
# 如果请求的URI对应一个实际存在的文件(-f)或目录(-d),
# 则不执行后续的重写规则,直接由Apache提供服务。
# 这确保了静态资源(如CSS、JS、图片)能够被直接访问。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 规则2: 将所有不匹配真实文件或目录的请求重写到 public/index.php
# ^(.*)$ 匹配所有URI路径,并将其作为捕获组传递。
# public/index.php 是我们的前端控制器。
# [L] 表示这是最后一条规则,停止处理后续规则。
# 此时,原始的请求URI(例如 /news/1?test=helloword)将通过 $_SERVER['REQUEST_URI']
# 完整地传递给 public/index.php。
RewriteRule ^(.*)$ public/index.php [L]配置说明:
通过这组规则,当用户访问http://localhost/css/style.css时,由于public/css/style.css是一个真实存在的文件(假设它存在),RewriteCond条件不满足,请求将直接由Apache处理。而当用户访问http://localhost/news/1?test=helloword时,由于/news/1不是一个真实的文件或目录,RewriteCond条件满足,请求将被重写到public/index.php。
当请求被重写到public/index.php后,PHP应用可以通过$_SERVER超全局变量访问原始的URL信息。
在public/index.php中,您可以这样获取和解析URL:
helloword // ) // 在这里,您可以根据 $path 和 $queryParameters 实现您的路由逻辑 // 例如: // require __DIR__ . '/../bootstrap/app.php'; // 引入应用启动文件 // $app->handleRequest($path, $queryParameters); // 路由处理
置文件)中,确保您网站的DocumentRoot或相关目录的Directory块中包含AllowOverride All或AllowOverride FileInfo。如果没有,.htaccess文件中的RewriteRule将不会生效。Options Indexes FollowSymLinks AllowOverride All # 确保这一行存在 Require all granted
通过上述.htaccess配置,您可以成功地将Apache服务器的Web根目录逻辑地指向项目的public/子目录,同时保留了静态资源的直接访问能力,并确保了所有动态请求都能被前端控制器(如public/index.php)接收并处理,且原始URL的路径和查询参数在PHP应用中保持完整可访问。这种设置是许多现代PHP框架(如Laravel、Symfony)推荐和使用的标准方式,为构建健壮、可维护的Web应用奠定了基础。