
is_dir() 判断目录时依赖相对路径,若未显式指定完整路径,会基于当前工作目录(而非 scandir() 的扫描路径)进行检查,导致结果不一致。解决方法是将文件名与根路径拼接后再判断。
`is_dir()` 判断目录时依赖相对路径,若未显式指定完整路径,会基于当前工作目录(而非 `scandir()` 的扫描路径)进行检查,导致结果不一致。解决方法是将文件名与根路径拼接后再判断。
在 PHP 中,is_dir() 是一个路径敏感函数——它不会自动继承 scandir() 所操作的目录上下文,而是始终以当前工作目录(即 getcwd() 返回的路径)为基准解析传入的路径字符串。这意味着:
- 当你在
/index.php中执行include $_SERVER['DOCUMENT_ROOT'].'/imports/header.php'时,脚本实际运行的工作目录通常是 Web 服务器配置的文档根目录(如/var/www/html),此时is_dir('directory1')等价于is_dir('/var/www/html/directory1')→ ✅ 成功识别; - 但当在
/directory1/index.php中执行相同include时,PHP 的当前工作目录可能已变为/var/www/html/directory1(尤其在 CLI 模式或某些 SAPI 配置下),此时is_dir('directory1')实际检查的是/var/www/html/directory1/directory1→ ❌ 不存在,返回false。
因此,原始代码中:
$dirs = array_filter($dirs, 'is_dir'); // ❌ 错误:仅传入 basename,无路径上下文
会导致不可靠的结果,与执行位置强耦合。
✅ 正确做法是:显式构造绝对路径再校验。修改 array_filter 回调函数如下:
立即学习“PHP免费学习笔记(深入)”;
$root = $_SERVER['DOCUMENT_ROOT'];
$dirs = scandir($root);
$dirs = array_filter($dirs, function($dir) use ($root) {
return is_dir($root . '/' . $dir) && $dir !== '.' && $dir !== '..';
});
// 过滤掉非目录项后,再移除 img、imports 等无需展示的目录
$dirs = array_diff($dirs, ['img', 'imports']);⚠️ 注意事项:
- 始终使用
$_SERVER['DOCUMENT_ROOT'](而非__DIR__或getcwd())确保路径指向 Web 根,避免因入口脚本位置不同引发歧义; - 在拼接路径时建议统一使用
/(PHP 在 Windows 上也能正确处理),或更健壮地使用DIRECTORY_SEPARATOR; -
scandir()返回的数组包含.和..,应优先过滤(如上例所示),避免后续逻辑误判; - 若需兼容符号链接,可改用
is_dir()+!is_link()组合判断,或直接使用is_dir(realpath($path))。
最终生成导航链接的完整安全写法示例:
<?php
$root = $_SERVER['DOCUMENT_ROOT'];
$entries = scandir($root);
$dirs = array_filter($entries, function($entry) use ($root) {
$path = $root . '/' . $entry;
return is_dir($path) && !in_array($entry, ['.', '..', 'img', 'imports']);
});
foreach ($dirs as $dir) {
$label = ucwords(str_replace('-', ' ', $dir));
echo "<a href=\"/$dir\"><p>$label</p></a>";
}
?>此方案彻底解耦了 is_dir() 对当前工作目录的依赖,确保无论从网站任意子路径引入该 header,都能稳定识别根目录下的真实子目录。



















