directoryiterator::current() 返回 splfileinfo 对象,需先调用 valid() 判断有效性,再通过 getfilename() 等方法获取文件信息,不可直接字符串拼接或 isset 判断。

DirectoryIterator::current() 返回什么类型?
DirectoryIterator::current() 返回的是一个 SplFileInfo 对象,不是字符串或数组。很多人误以为它直接返回文件名,结果在 echo 时看到类似 object(SplFileInfo)#2 (0) { } 的输出,或者调用 ->getFilename() 报错“Call to a member function getFilename() on null”。
常见错误现象是:没检查 valid() 就直接调用 current(),导致返回 null;或者把 current() 当成字符串拼接,比如 "file: " . $iterator->current(),触发隐式转换失败。
- 必须先确认
$iterator->valid()为true,再调用current() - 拿到对象后,用
->getFilename()、->isFile()、->getSize()等方法取具体信息 - 不能对
current()结果做isset()或empty()判断——它永远不是空值(除非valid()为 false)
为什么 foreach 循环里不用手动调用 next()?
因为 foreach 会自动调用 DirectoryIterator 实现的 Iterator 接口方法:rewind()、valid()、current()、key()、next()。你写 foreach ($dir as $file),PHP 内部已经帮你做了完整迭代流程。
但手动 while 循环时,必须显式调用 next(),否则会死循环在第一个项上。典型错误是:
$iterator = new DirectoryIterator(__DIR__);
while ($iterator->valid()) {
echo $iterator->getFilename() . "\n";
// 忘了写 $iterator->next();
}
这种写法会无限输出第一个文件名(通常是 .),直到超时或内存耗尽。
-
foreach安全、简洁,适合大多数遍历场景 - 手动 while +
next()仅在需要中途 break 或条件跳过时才有意义 - 一旦用了手动循环,
next()必须放在循环体末尾,且不能被continue跳过
getFilename() 和 getBasename() 有什么区别?
getFilename() 返回当前项的原始名称(如 .gitignore、config.php),不含路径,也不处理后缀;getBasename() 可选传入 $suffix 参数,用于剥离指定后缀(比如 $file->getBasename('.php') 返回 config)。
容易踩的坑是:误以为 getBasename('.jpg') 能过滤非 JPG 文件——它只是字符串截断,不校验真实扩展名。例如对 report.pdf 调用 getBasename('.jpg'),结果仍是 report.pdf,不会报错也不会返回空。
- 判断文件类型请用
$file->getExtension()或pathinfo($file->getPathname(), PATHINFO_EXTENSION) -
getBasename()主要用于生成友好显示名,比如去掉通用后缀.log或.tmp - 两者都不处理 Unicode 文件名的编码问题,如果目录含中文名,确保脚本和终端编码一致(通常是 UTF-8)
DirectoryIterator 遍历时遇到权限拒绝怎么处理?
当 new DirectoryIterator('/var/log') 报错 Permission denied,不是代码写错了,而是 PHP 进程用户(如 www-data)没有读取该目录的权限。错误信息通常是:Uncaught RuntimeException: DirectoryIterator::__construct(/var/log): failed to open dir: Permission denied。
不能靠 try/catch 吞掉异常就完事——这会让整个目录跳过,且不提示哪一层出问题。更合理的做法是提前检测可读性,并给出明确路径反馈。
- 创建前先用
is_readable($path)检查,不可读就记录日志或跳过 - 若需强制访问,改目录权限(
chmod 755 /var/log)或调整所属组(chgrp www-data /var/log && chmod g+r /var/log) - 注意
open_basedir限制:即使权限足够,若 PHP 配置了open_basedir,超出范围的路径会直接拒绝,错误提示仍是Permission denied
最常被忽略的是 open_basedir 和 SELinux/AppArmor 这类系统级限制,它们不会出现在 PHP 错误日志里,得查系统日志(/var/log/audit/audit.log)才能定位。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











