在本地使用phpEnv搭建PHP开发环境时,很多朋友会把项目整个目录挂在Nginx站点下。这时一些不该被外部访问的文件,比如环境变量文件、数据库脚本、版本库目录,就需要通过Nginx规则排除掉。但在phpEnv里直接改配置,经常会遇到写了排除规则却依然能访问的情况。本文就来讲清楚phpEnv下Nginx排除文件的正确配置方式。

为什么phpEnv里的排除规则容易失效
phpEnv集成环境中的Nginx,默认站点配置往往把PHP请求的处理放在比较靠前的位置,而且通常使用正则location来匹配脚本入口。Nginx的location匹配规则里,正则location优先级高于普通前缀location,如果你把排除规则写成了前缀location,而访问路径又被PHP正则捕获,那么排除就会失效。
另外一个常见原因是phpEnv提供了可视化的站点配置面板,它在保存时会重新生成Nginx的server块,把你手动在文件里加的location覆盖掉。很多人改了nginx.conf里的include文件,结果一点面板保存,规则全没。所以排除配置必须写在phpEnv允许自定义的站点配置段中,或者通过它提供的附加配置入口写入。
使用精确location做文件排除
最稳妥的排除方式是利用精确匹配前缀location,并在内部直接返回403。因为精确前缀location(不带正则)在匹配相同路径时优先级足够高,而且我们可以把敏感文件一一列出来。下面是在phpEnv站点附加配置中常用的写法:
# 排除根目录下的敏感文件
location = /config.ini {
return 403;
}
location = /database.sql {
return 403;
}
location = /.env {
return 403;
}
# 排除某类后缀或目录,用前缀匹配
location ^~ /vendor/ {
return 403;
}
location ^~ /.git/ {
return 403;
}
location ~* .(log|sql|bak)$ {
return 403;
}
上面代码中,location = 是精确匹配,请求路径必须完全相等才会命中;^~ 表示前缀匹配且不做正则后续检查,适合屏蔽整个目录;最后的 ~* 是正则忽略大小写,用来拦后缀。把这些规则放在phpEnv生成的PHP处理location之前,就能优先拦截。
需要注意,phpEnv默认可能把 index.php 的入口写成 location ~ .php$ 这样的正则。如果你的排除文件恰好是.php结尾,比如 secret.php,那么精确location = /secret.php 依然会优先于正则,所以直接用等于号最安全。
在phpEnv面板中落地配置
打开phpEnv,进入对应站点的“配置文件”或“Nginx附加配置”区域(不同版本叫法略有差异,但都支持自定义server级片段)。把上面的location块粘贴进去,保存并重启Nginx。不要直接去改安装目录里的nginx.conf主文件,因为面板升级或点保存时会还原。
<?php
// 简单验证排除是否生效的本地脚本思路
$blocked = ['/config.ini', '/.env', '/database.sql'];
$req = $_SERVER['REQUEST_URI'] ?? '';
if (in_array($req, $blocked)) {
header('HTTP/1.1 403 Forbidden');
exit;
}
echo '正常访问';
?>
这段PHP只是示意:即便Nginx没拦住,应用层也可以做二层防护。但根本解决还是在Nginx层挡掉,减少PHP进程开销。
配置完之后,可以用浏览器或curl直接请求被排除的文件路径,看是否返回403。如果还是能下载,检查phpEnv是否启用了“静态文件优先”之类的缓存代理,或者确认附加配置是否被面板正确写入了server块。也可以临时打开Nginx的error_log看匹配到了哪个location。
常见误区与建议
有人喜欢用 deny all; 指令来做排除,这本身没问题,但如果在错误的地方写,比如写在正则PHP location里面,会导致所有PHP都拒绝。建议统一用 return 403; 语义更清晰,也方便以后改成404迷惑扫描器。
还有人把排除规则写进http全局块,以为对所有站点生效,结果phpEnv每个站点单独include,全局并未加载。应当针对具体站点配置,或者修改phpEnv的站点模板,让新建站点自动带排除段。养成把敏感文件移出Web根目录的习惯,比依赖Nginx排除更可靠,但本地调试时上面的方法足够实用。
| 排除方式 | 适用场景 | 优先级特点 |
|---|---|---|
| 精确匹配 = | 单个明确文件 | 最高,优先于正则 |
| 前缀 ^~ | 整个目录 | 高于正则,停止后续正则 |
| 正则 ~* | 某类后缀 | 按出现顺序,低于精确 |
掌握这几类写法,在phpEnv里配置Nginx排除文件就不会再踩坑。遇到规则不生效,先想优先级,再查面板覆盖,基本都能解决。