PHP递归插入MySQL失效:遍历目录未触发递归调用
问题分析与修复方案
核心问题点
- 路径判断错误:
is_dir($scanf[$s])仅传入子项名称而非完整路径,无法正确识别目录;递归调用时传的也是相对文件名,子函数找不到目标目录。 - 循环索引混乱:unset掉
.和..后数组索引被打乱,原for($s=2; $s<count($scanf); $s++)的遍历逻辑会跳过元素或访问不存在的索引。 - 重复引入文件:
include "./modular/filesLogic.php"放在函数内部,每次递归都会重复引入,易引发函数/变量重复定义错误。 - 目录文件大小处理:调用
filesize()处理目录会返回false,直接插入数据库会导致数值错误。 - SQL注入风险:直接将文件名拼入SQL语句,存在严重的注入漏洞。
修复后的代码
// 将include移到函数外部,避免重复引入 include "./modular/filesLogic.php"; function insertToTable($dire){ global $conn; // 确保数据库连接变量在函数内可用 $scanf = scandir($dire); // 过滤掉.和..,并重新索引数组 $scanf = array_filter($scanf, function($item) { return $item !== '.' && $item !== '..'; }); $scanf = array_values($scanf); foreach($scanf as $item){ $fullPath = $dire . "/" . $item; $inamewoext = pathinfo($item, PATHINFO_FILENAME); $datec = date("Y-m-d"); if(is_dir($fullPath)){ $iextension = "dir"; $sze = 0; // 目录大小设为0,可根据需求调整 // 递归调用时传入完整路径 insertToTable($fullPath); } else { $iextension = pathinfo($item, PATHINFO_EXTENSION); $sze = filesize($fullPath); // 处理文件大小获取失败的情况 if($sze === false) $sze = 0; } // 使用预处理语句防止SQL注入 $stmt = $conn->prepare("SELECT * FROM files WHERE name = ?"); $stmt->bind_param("s", $inamewoext); $stmt->execute(); $resi = $stmt->get_result(); if(mysqli_num_rows($resi) <= 0){ $stmtInsert = $conn->prepare("INSERT INTO files (name, ftype, dateup, size, downloads, dirGroup) VALUES (?, ?, ?, ?, 0, ?)"); $stmtInsert->bind_param("sssis", $inamewoext, $iextension, $datec, $sze, $dire); $stmtInsert->execute(); } // 关闭预处理语句 $stmt->close(); if(isset($stmtInsert)) $stmtInsert->close(); } } insertToTable("uploads");
关键修复说明
- 完整路径处理:所有文件/目录操作都使用
$fullPath,确保目录判断和递归调用的正确性。 - 数组遍历优化:用
array_filter过滤无用项后重新索引数组,再用foreach遍历,避免索引混乱。 - 避免重复引入:将
include移到函数外部,仅加载一次。 - 目录大小兼容:给目录设置默认大小,同时处理文件大小获取失败的异常情况。
- SQL注入防护:使用MySQLi预处理语句绑定参数,杜绝直接拼接SQL的风险。
内容的提问来源于stack exchange,提问作者KleiaTMT
相关产品推荐
相关产品推荐

