使用DirectoryIterator迁移文件系统数据到数据库报错求助
文件系统转数据库迁移代码报错修复
问题概述
要将home多级目录下的数据迁移到数据库,使用DirectoryIterator遍历目录时抛出致命错误:
Uncaught UnexpectedValueException: DirectoryIterator...(第53行)
排查后确认问题根源在第72行的路径拼接错误,以下是具体分析和修复方案。
原代码
function go($path){ global $db; $it = new DirectoryIterator($path); // line 53 foreach ($it as $a){ if ($a->isDot()){continue;} if($a->isDir()){ $fopath = $it->getPathname(); $foname = $a->getFilename(); $foid = uniqid(); $sq = "insert into nts (id, what, title) values (:aid, :awhat, :atitle)"; $st = $db->prepare($sq); $st->execute([":aid" => $foid, ":awhat" => 'fo', ":atitle" => $foname]); $arr = array_filter(glob($fopath . "/*"), 'is_file'); foreach($arr as $el){ $fiid = uniqid(); $finame = basename($el, '.txt'); $story = file_get_contents($el); $sq = "insert into nts (id, what, par, title, story) values (:aid, :awhat, :apar, :atitle, :astory)"; $st = $db->prepare($sq); $st->execute([":aid" => $fiid, ":awhat" => 'fi', ":apar" => $foid, ":atitle" => $finame, ":astory" => $story]); } go("{$path}{$a->getPathname()}/"); // line 72 } } }} } go("home/");
错误分析
- 路径拼接错误(第72行):
$a->getPathname()返回的是目录完整路径(如home/subdir),和传入的$path(如home/)拼接后会变成home/home/subdir/,这是无效路径,导致DirectoryIterator初始化失败抛出异常。 - 文件夹路径获取错误(第60行):
$it->getPathname()是迭代器本身的路径,应该用$a->getPathname()获取当前子文件夹的完整路径,否则glob会遍历错误目录。 - 语法错误:函数末尾多了两个闭合大括号,还有一个多余的
},会导致脚本解析失败。
修复后的代码
function go($path){ global $db; // 提前验证路径有效性 if (!is_dir($path)) { error_log("无效目录路径:{$path}"); return; } try { $it = new DirectoryIterator($path); foreach ($it as $a){ if ($a->isDot()) continue; if($a->isDir()){ $fopath = $a->getPathname(); $foname = $a->getFilename(); $foid = uniqid(); // 插入文件夹记录 $sq = "insert into nts (id, what, title) values (:aid, :awhat, :atitle)"; $st = $db->prepare($sq); $st->execute([":aid" => $foid, ":awhat" => 'fo', ":atitle" => $foname]); // 遍历当前文件夹下的文件 $files = array_filter(glob($fopath . "/*"), 'is_file'); foreach($files as $file){ $fiid = uniqid(); $finame = basename($file, '.txt'); $story = file_get_contents($file); // 插入文件记录 $sq = "insert into nts (id, what, par, title, story) values (:aid, :awhat, :apar, :atitle, :astory)"; $st = $db->prepare($sq); $st->execute([":aid" => $fiid, ":awhat" => 'fi', ":apar" => $foid, ":atitle" => $finame, ":astory" => $story]); } // 递归遍历子目录:直接传入完整路径 go($fopath); } } } catch (UnexpectedValueException $e) { error_log("遍历目录失败:{$path},错误信息:{$e->getMessage()}"); } } go("home/");
额外优化点
- 增加路径验证和异常捕获,避免单个目录出错导致整个迁移中断;
- 替换变量名(如
$arr改为$files)提升代码可读性; - 建议移除
global $db,改为将数据库连接作为参数传入,增强代码复用性; uniqid()存在重复风险,可考虑使用数据库自增ID或UUID生成函数替代。
内容的提问来源于stack exchange,提问作者provance
相关产品推荐
相关产品推荐

