PHPRad导入CSV文件时如何更新aflossingen表现有记录
CSV导入匹配主键更新aflossingen表记录问题排查与修复
需求说明
- 目标表:
aflossingen - 表字段:
AflossingID(主键)、VoorschotID、Aflossingdatum、Aflossingsbedrag、Afgelost、Saldo - 实现目标:导入CSV格式文件时,根据
AflossingID匹配已有记录,更新对应字段值,替代原有仅支持INSERT新增的逻辑。
原自定义代码的核心错误
你的更新逻辑无任何效果,是因为存在以下硬伤:
- SQL语句逻辑完全失效:写的
UPDATE aflossingen SET Aflossingdatum = Aflossingdatum,Afgelost = Afgelost, Saldo = Saldo WHERE AflossingID = AflossingID本质是把字段值设为自身,WHERE条件对所有记录生效,既不会修改任何数据,还会触发全表扫描,完全没有引用CSV读取到的动态值。 - 预处理参数绑定完全错误:参数类型定义为
"ss"(仅2个字符串参数),实际传入了5个变量,类型、数量均不匹配,预处理语句无法正常执行。 - 数据库连接不存在:代码中直接调用全局变量
$connection,但PHPRad控制器中数据库实例需通过$this->GetModel()获取,不存在该全局连接变量,调用mysqli函数会直接触发未定义变量错误。 - 表单字段名不匹配:原PHPRad生成的上传表单文件字段名为
file,提交判断无额外importcsv参数,你的自定义代码判断的提交参数、读取的文件字段名均和实际表单不匹配,根本不会进入文件处理分支。 - 未跳过CSV表头:逻辑默认把CSV第一行的列名当成数据执行,会产生大量无效执行。
- UPDATE字段遗漏:已经从CSV中读取了
Aflossingsbedrag值,但SQL语句中完全没有写入该字段的更新逻辑。
可直接使用的修复代码
直接替换控制器里的import_data方法即可,完全兼容PHPRad原有逻辑,保留原有的文件格式校验、错误提示能力:
function import_data(){ if(!empty($_FILES['file'])){ $finfo = pathinfo($_FILES['file']['name']); $ext = strtolower($finfo['extension']); if(!in_array($ext , array('csv'))){ $this->set_flash_msg("不支持的文件格式,请上传CSV文件", "danger"); } else{ $file_path = $_FILES['file']['tmp_name']; if(!empty($file_path)){ $db = $this->GetModel(); $tablename = $this->tablename; $handle = fopen($file_path, 'r'); $updated_count = 0; $error_count = 0; $is_first_row = true; // 标记跳过表头行 while (($row = fgetcsv($handle, 0, ',', '"')) !== FALSE) { // 跳过第一行表头 if($is_first_row){ $is_first_row = false; continue; } // 按CSV列顺序读取字段,列索引从0开始,顺序需和CSV实际列顺序对齐 // 默认顺序:0=AflossingID,1=VoorschotID,2=Aflossingdatum,3=Aflossingsbedrag,4=Afgelost,5=Saldo $aflossing_id = trim($row[0]); $voorschot_id = trim($row[1]); $aflossing_datum = trim($row[2]); $aflossings_bedrag = trim($row[3]); $afgelost = trim($row[4]); $saldo = trim($row[5]); // 主键ID为空直接跳过 if(empty($aflossing_id)){ $error_count++; continue; } // 组装更新数据 $update_data = array( 'VoorschotID' => $voorschot_id, 'Aflossingdatum' => $aflossing_datum, 'Aflossingsbedrag' => $aflossings_bedrag, 'Afgelost' => $afgelost, 'Saldo' => $saldo ); // 按主键AflossingID匹配更新,调用框架自带方法自动做安全过滤 $db->where('AflossingID', $aflossing_id); $update_status = $db->update($tablename, $update_data); if($update_status){ $updated_count++; }else{ $error_count++; } } fclose($handle); if($error_count > 0){ $this->set_flash_msg("导入完成,成功更新{$updated_count}条记录,{$error_count}条记录更新失败", "warning"); }else{ $this->set_flash_msg("导入完成,成功更新{$updated_count}条记录", "success"); } } else{ $this->set_flash_msg("文件上传失败", "danger"); } } } else{ $this->set_flash_msg("请选择要上传的CSV文件", "warning"); } $this->redirect("aflossingen"); }
使用注意
- 请确保上传的CSV列顺序和代码中读取顺序一致,如果你的CSV列顺序有调整,对应修改代码里
$row[x]的索引映射关系即可。 - 代码默认自动跳过CSV第一行表头,无需手动删除表头行。
- 调用框架自带的
$db->update()方法比原生mysqli兼容性更好,自动实现SQL注入防护,不会出现连接变量未定义的问题。
内容的提问来源于stack exchange,提问作者Unknown04
相关产品推荐
相关产品推荐

