parse_url($_server['request_uri'], php_url_path) 是最简但最关键的解析起点,用于提取干净路径以避免查询参数、锚点和编码字符干扰,后续需结合http方法拼接匹配路由并统一处理404。

parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 是最简但最关键的解析起点
几乎所有手写路由的第一步,都是从 $_SERVER['REQUEST_URI'] 中提取干净路径,而不是直接用整个字符串。因为 REQUEST_URI 可能带查询参数(如 /user/123?tab=profile),而路由匹配通常只关心路径部分。
必须用 parse_url(..., PHP_URL_PATH) 提取,不能用 $_GET['url'] 或正则硬切 —— 后者在含问号、井号、编码字符时极易出错。
- 错误示例:
$path = strtok($_SERVER['REQUEST_URI'], '?')会漏掉锚点(#section)和 URL 编码的斜杠(%2F) - 正确做法始终是:
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) - 注意:该函数返回的是原始路径,不自动解码,如需处理中文或特殊字符,后续再调用
urldecode()
静态路由匹配用 array_key_exists(),但必须拼合 HTTP 方法
只按路径匹配(如 '/user')会导致 GET 和 POST 冲突。真实项目中,路由规则必须绑定方法,否则无法支持 RESTful 接口。
典型注册格式是:'GET /user' => 'UserController@list',然后用 "{$_SERVER['REQUEST_METHOD']} {$uri}" 拼出键去查表。
- 遗漏方法拼接是新手最常踩的坑:写成
if ($routes[$uri]),结果 POST /user 被当成 GET 处理 - 大小写敏感:PHP 数组键区分大小写,
'get /user'不等于'GET /user' - 空格不能省:
'GET/user'和'GET /user'是两个不同键
动态路由靠 preg_replace + 命名捕获,不是简单 str_replace
把 /user/{id} 转成正则 #^/user/(?P<id>[^/]+)$#</id> 才能安全提取参数。用 str_replace('{id}', '(\d+)', $route) 看似快,但无法约束类型、无法命名、无法处理嵌套占位符(如 {slug}-{id})。
标准转换逻辑是:
foreach ($routes as $route => $handler) {
$pattern = preg_replace('#/{([^/]+)}#', '/(?P[^/]+)', $route);
$pattern = '#^' . preg_quote($pattern, '#') . '$#';
if (preg_match($pattern, $uri, $matches)) {
// $matches 包含命名键,如 $matches['id']
break;
}
}
-
preg_quote()必须加:否则/user.{ext}这类含点号的路由会被正则误解释 - 捕获组用
(?P<name>...)</name>而非(...),方便后续用键名取值,不用记索引 - 不要用
.*替代[^/]+:前者会跨路径段匹配,破坏层级语义
404 响应必须在所有匹配逻辑之后统一处理
很多人在每个 if 分支里写 exit 或 die,导致后续中间件、日志、异常兜底逻辑被跳过。真正健壮的路由分发,应该把匹配结果存为变量,最后统一判断是否命中。
- 反模式:
if ($uri === '/home') { include 'home.php'; exit; } - 推荐方式:设
$found = null,匹配成功时赋值为['controller' => 'Home', 'action' => 'index', 'params' => []],循环结束后检查if (!$found) - HTTP 状态码要显式设置:
http_response_code(404),否则默认是 200,SEO 和调试都会出问题
'POST /api/users' => ['middleware' => ['auth', 'json'], 'handler' => 'Api\UserController@store'] 这种结构,比纯字符串映射更易维护。但那已经超出基础解析范畴了。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











