htaccess伪静态重写后如何获取PHP入口文件所在目录基础URL
问题原因
原有代码直接使用$_SERVER['REQUEST_URI']拼接路径,这个变量存储的是用户发起请求的完整URI,包含伪静态转发后的路径部分(比如测试场景里的/index.js),拼接后自然会出现路径重复的错误。
要兼容任意部署路径,核心是不要从请求URI反推部署路径,直接通过PHP内置的$_SERVER['SCRIPT_NAME']获取入口文件index.php的真实服务端路径,这个值不受重写规则影响,不管部署在根目录还是多少层子目录都能准确拿到入口位置。
修正方案
- 优化原有
is_https()函数的判断逻辑,兼容Apache环境下HTTPS值为off的场景 - 新增基础URL获取函数,通过
SCRIPT_NAME计算入口所在目录的URL,自动适配任意部署层级 - 调整路径拼接逻辑,直接在基础URL后拼接目标目录和
q参数传递的路径,丢弃REQUEST_URI里的伪静态路径部分
修正后的完整代码如下:
function is_https() { // apache环境判断 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { return true; } // heroku等反向代理场景判断 if (isset($_SERVER['HTTP_X_FORWARDED_PORT']) && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { return $_SERVER['HTTP_X_FORWARDED_PORT'] == 443 || $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'; } return false; } function get_base_url() { $scheme = is_https() ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST']; // 获取入口文件index.php的服务端路径,不受重写规则影响 $entryPath = $_SERVER['SCRIPT_NAME']; // 提取入口文件所在目录,统一处理末尾斜杠 $basePath = rtrim(dirname($entryPath), '/'); return "{$scheme}://{$host}{$basePath}/"; } function main() { $addresses = json_decode(file_get_contents('ip.json')); $blocked = in_array($_SERVER['REMOTE_ADDR'], $addresses); $baseUrl = get_base_url(); // 拼接目标路径,ltrim去掉q参数开头的斜杠避免双斜杠 $url = $baseUrl . ($blocked ? 'block/' : 'game/') . ltrim($_GET['q'], '/'); echo $url; // 如果只是读取本地文件,不需要走HTTP curl,直接用__DIR__拼接磁盘路径读取性能更好 // 例:$filePath = __DIR__ . ($blocked ? '/block/' : '/game/') . ltrim($_GET['q'], '/'); } if (isset($_GET['q'])) { main(); }
效果验证
- 本地测试场景:访问
http://localhost/~kuba/jcubic/support/order/app/index.js时,SCRIPT_NAME值为/~kuba/jcubic/support/order/app/index.php,计算得到的基础URL为http://localhost/~kuba/jcubic/support/order/app/,未封禁时生成的URL为http://localhost/~kuba/jcubic/support/order/app/game/index.js,符合预期。 - 根目录部署场景:访问
https://example.com/index.js时,SCRIPT_NAME值为/index.php,计算得到的基础URL为https://example.com/,未封禁时生成的URL为https://example.com/game/index.js,符合要求。
额外优化提示:如果只是需要读取服务器本地
/game/、/block/目录下的文件,完全不需要构造HTTP URL走curl请求,直接用PHP常量__DIR__(也就是当前index.php所在的磁盘目录)拼接文件路径读取即可,性能更高,也不会受服务器环境、域名配置的影响。
内容的提问来源于stack exchange,提问作者jcubic
相关产品推荐
相关产品推荐

