
本文介绍如何使用 `parse_url()` 和 `parse_str()` 安全、可靠地分离并访问 url 的路径段(如 `/page/1`)和查询参数(如 `?id=1`),避免手动 `explode()` 带来的边界问题,并适配 nginx 的 `try_files` 重写规则。
在现代 PHP 路由处理中,混合式 URL(如 example.com/page/1?id=abc&lang=zh)十分常见。你当前通过 explode('/', $_SERVER['REQUEST_URI']) 手动分割路径的方式虽简单,但存在明显缺陷:它无法区分路径部分与查询字符串(? 后内容),且易受空段、编码字符、锚点(#)等干扰,导致 $REQ[1] 取值不可靠。
更健壮的做法是先用 parse_url() 解析完整 URI,再分别处理路径与查询参数:
// 1. 解析当前请求的完整 URI(自动剥离 query 和 fragment)
$parsed = parse_url($_SERVER['REQUEST_URI']);
$path = $parsed['path'] ?? '';
$query = $parsed['query'] ?? '';
// 2. 提取路径段(安全去除空项和前导/)
$pathSegments = array_filter(
explode('/', trim($path, '/')),
function($v) { return $v !== ''; }
);
$pathSegments = array_values($pathSegments); // 重置索引为 0,1,2...
// 3. 解析查询参数到关联数组
parse_str($query, $queryParams);此时,你可以像原来一样访问路径段,同时还能直接读取 GET 参数:
// 示例:匹配 /page/{id} 并支持 ?title=xxx 等额外参数
if (count($pathSegments) >= 2 && $pathSegments[0] === 'page') {
$pageId = $pathSegments[1] ?? null;
$title = $queryParams['title'] ?? null;
$lang = $queryParams['lang'] ?? 'en';
echo "Rendering page ID: {$pageId}, title: '{$title}', lang: {$lang}";
}⚠️ 重要注意事项:
立即学习“PHP免费学习笔记(深入)”;
- $_SERVER['REQUEST_URI'] 包含原始请求路径(含查询字符串),parse_url() 能准确识别 ? 分界,无需手动截断;
- parse_str() 会自动 URL 解码(如 %20 → 空格),且支持嵌套语法(如 user[name]=John&user[age]=30),生成多维数组;
- Nginx 配置 try_files $uri /index.php?$query_string; 已确保所有请求(包括带参数的)均正确转发至 index.php,$_SERVER['REQUEST_URI'] 值保持完整可用;
- 切勿对 $pathSegments 或 $queryParams 直接用于 SQL 查询或输出——务必进行类型校验、白名单过滤及输出转义(如 htmlspecialchars())。
综上,用 parse_url() + parse_str() 替代 explode() 是面向生产环境的推荐实践:语义清晰、兼容性强、不易出错,也为后续升级至 PSR-7 请求对象或框架路由打下坚实基础。











