
is_dir() 判断目录时依赖当前工作目录而非绝对路径,若传入相对路径名(如 'directory1'),它会在执行脚本所在目录下查找,导致跨目录包含时结果不一致。正确做法是显式拼接 $_SERVER['DOCUMENT_ROOT'] 构造完整路径后再校验。
`is_dir()` 判断目录时依赖当前工作目录而非绝对路径,若传入相对路径名(如 `'directory1'`),它会在执行脚本所在目录下查找,导致跨目录包含时结果不一致。正确做法是显式拼接 `$_server['document_root']` 构造完整路径后再校验。
在 PHP 中,is_dir() 是一个路径敏感函数,它接收的参数会被解释为相对于当前工作目录(Current Working Directory, CWD) 的路径,而非相对于 $_SERVER['DOCUMENT_ROOT'] 或文件系统根目录。这一点正是你遇到问题的核心原因。
当你在 /index.php 中 include header.php 时,脚本的当前工作目录通常是 Web 服务器配置的文档根目录(即 $_SERVER['DOCUMENT_ROOT']),因此 scandir($_SERVER["DOCUMENT_ROOT"]) 返回的条目(如 'directory1')直接传给 is_dir('directory1') 仍能正确识别——因为此时 CWD 就是文档根目录。
但当请求 /directory1/index.php 时,虽然 include 语句仍指向同一份 header.php,PHP 解析 is_dir($dir) 时,$dir(如 'directory1')被当作相对于 /directory1/ 目录的路径来判断,即实际检查的是 /directory1/directory1 是否为目录,显然不存在,故返回 false。同理,'img'、'imports' 等也因路径错位而全部失效,仅 . 和 .. 恒存在,所以第二次 print_r($dirs) 只剩这两个元素。
✅ 正确解决方案:始终使用绝对路径调用 is_dir()
将原代码中:
$dirs = array_filter($dirs, 'is_dir');
替换为显式拼接文档根路径的匿名函数:
$dirs = array_filter($dirs, function($dir) {
$fullPath = $_SERVER['DOCUMENT_ROOT'] . '/' . ltrim($dir, '/');
return is_dir($fullPath);
});
? 增强健壮性提示:使用
ltrim($dir, '/')避免双斜杠(如//directory1),也可改用DIRECTORY_SEPARATOR兼容 Windows,但 Web 环境通常为 Unix-like 系统,/安全可用。
完整修正后的 header.php 片段如下:
<?php $dirs = scandir($_SERVER["DOCUMENT_ROOT"]);
// print_r($dirs); // 调试用,上线前建议移除
// 关键修复:基于 DOCUMENT_ROOT 构造绝对路径再判断
$dirs = array_filter($dirs, function($dir) {
$fullPath = $_SERVER['DOCUMENT_ROOT'] . '/' . ltrim($dir, '/');
return is_dir($fullPath) && $dir !== '.' && $dir !== '..';
});
// 过滤掉 img、imports 等非导航目录(注意:此时 $dirs 键值保留原始名)
$dirs = array_diff($dirs, ['img', 'imports']);
foreach ($dirs as $dir) {
$displayName = ucwords(str_replace('-', ' ', $dir));
echo "<a href=\"/$dir\"><p>$displayName</p>";
}
?>
? 额外建议:
- 避免依赖
getcwd()或dirname(__FILE__)推导路径,它们易受chdir()或 CLI 模式影响; - 若需更高可移植性,可封装为工具函数:
function isDirInDocRoot($basename) { return is_dir($_SERVER['DOCUMENT_ROOT'] . '/' . ltrim($basename, '/')); } $dirs = array_filter($dirs, 'isDirInDocRoot'); - 生产环境应添加错误抑制(如
@is_dir(...))或异常处理,防止因权限问题中断渲染。
总之,is_dir() 的“位置感知”特性不是 Bug,而是设计使然;明确路径上下文,始终传递绝对路径,即可彻底规避此类跨目录包含引发的逻辑偏差。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











