综合

php获取网站根目录

时间:2010-12-5 17:23:32  作者:焦点   来源:焦点  查看:  评论:0
内容摘要:打开编辑器,新建一个 test.php,写下一行 echo $_SERVER['DOCUMENT_ROOT'];,浏览器里跑一下。大概率你会看到类似 /var/www/html 或者 /usr/sha

打开编辑器,取网新建一个 test.php,站根写下一行 echo $_SERVER['DOCUMENT_ROOT'];,目录浏览器里跑一下。取网大概率你会看到类似 /var/www/html 或者 /usr/share/nginx/html 的站根东西。这就是目录 PHP 给你的网站根目录——物理路径,服务器文件系统里的取网绝对位置。很多人第一次拿到这个值就以为万事大吉,站根直接拿去拼文件路径了。目录我干过这事,取网结果在本地 Windows 开发环境跑得好好的站根,传到 Linux 服务器上直接 404。目录原因?取网Windows 下 $_SERVER['DOCUMENT_ROOT'] 返回的是 C:/xampp/htdocs,斜杠方向都不一样。站根

这个超全局变量到底靠不靠谱,目录得看谁在跑 PHP。Apache 的 mod_php 模式下,DocumentRoot 指令配的是什么,它就返回什么,稳得很。但换成 Nginx + PHP-FPM,情况就微妙了。Nginx 自己有个 root 指令,PHP-FPM 的 pool 配置里又有个 chdir 选项,两边的“根”可能不是同一个东西。我见过一个案例:Nginx 配置 root /data/site/public;,PHP-FPM 的 chdir 设成了 /data/site,结果 $_SERVER['DOCUMENT_ROOT'] 返回的是 /data/site,而不是 /data/site/public。代码里用它去拼静态资源路径,全挂。

那不用 $_SERVER,换 dirname(__FILE__) 行不行?这取决于你文件放哪儿。如果入口文件就在根目录,dirname(__FILE__) 确实等于根目录。但项目稍微有点结构,入口文件在 /public/index.php,那 dirname(__FILE__) 拿到的是 /public,不是根。你得再往上跳一层:dirname(dirname(__FILE__))。这种写法在 Laravel、ThinkPHP 这些框架里很常见,它们不信任 $_SERVER,自己算路径。

还有个偏方是 realpath('.')。它返回当前工作目录的绝对路径。PHP 脚本的工作目录默认是入口文件所在目录,但可以被 chdir() 改掉。你要是用了什么自动加载器或者 Composer 的 autoload,它内部可能就 chdir 过。所以 realpath('.') 拿到的值,有时候跟你预期的不一样。我调试过一个线上问题,本地 realpath('.') 返回项目根,线上返回了 /tmp,查了半天发现是某个定时任务脚本里有一行 chdir('/tmp') 没恢复。

最稳的办法其实是组合拳。定义一个常量,比如 define('ROOT_PATH', dirname(__DIR__)),放在入口文件里。这样不管服务器怎么配,路径都从文件自身位置推导,跟 $_SERVER 和当前工作目录都没关系。代价是你得保证入口文件的位置固定,别今天放根目录明天挪到子目录。框架都这么干,不是没道理的。

顺便说一句,$_SERVER['DOCUMENT_ROOT'] 在 CLI 模式下直接是空的。你写个脚本用 php script.php 跑,拿这个值去拼路径,拼出来就是 /uploads/xxx 这种从根开始的绝对路径,铁定找不到文件。所以但凡代码要在 Web 和 CLI 两种模式下复用,就别碰 $_SERVER['DOCUMENT_ROOT']。用 __DIR__ 或者 dirname(__FILE__) 自己算,累是累点,但不会半夜被报警叫醒。

最后提一个容易被忽略的点:符号链接。网站根目录如果是个软链,比如 /var/www/html -> /data/app/current,$_SERVER['DOCUMENT_ROOT'] 返回的是链接路径还是真实路径?取决于服务器配置。Apache 默认给链接路径,Nginx 也是。但 realpath() 会解析到真实路径。你要是用 realpath 拼路径,日志里记录的路径可能跟运维看到的不是同一个,排查问题的时候能把你绕晕。我的习惯是统一用 __DIR__ 系,不碰 realpath,也不碰 $_SERVER。简单,可预测,跨环境一致。

最近更新
热门排行
copyright © 2026 powered by 烟消火灭网   sitemap