用phpspreadsheet将excel数据导入数据库需四步:装库并刷新自动加载、安全移动文件后显式创建reader读取、映射列名并清洗数据、分批插入且事务保障。

想在ThinkPHP项目里把Excel表格里的数据一键塞进数据库,又不想被报错卡住、不看文档就动手、反复重装库、改命名空间改到怀疑人生——这篇文章只讲你上传完文件后,从第一行代码开始到数据真正落库的完整路径,每一步都踩过坑。
先装对库,别让Class not found拦在第一步
执行这条命令安装phpspreadsheet(不是PHPExcel,它已停止维护):
composer require phpoffice/phpspreadsheet
装完别急着写代码,先刷新自动加载缓存:
composer dump-autoload
【必须做】确认你的ThinkPHP项目已正确引入vendor/autoload.php——TP6默认做了,但如果你手动改过入口文件或用了自定义加载器,这里漏掉就会报“Class not found”。
在控制器顶部写这行引入,一个字都不能少:
use PhpOffice\PhpSpreadsheet\IOFactory;
上传文件后,安全移动再读取
别直接用$_FILES['file']['tmp_name']传给IOFactory::load()——框架可能已清理临时文件,路径失效或权限不足。
第一步:创建可读目录
在runtime/下新建upload/子目录(如runtime/upload/),确保PHP进程有写入权限。
第二步:用move_uploaded_file()转移文件
复制临时文件到runtime/upload/,并生成唯一文件名(例如:date('YmdHis').rand(100,999).'.xlsx')。
第三步:取真实扩展名,硬匹配reader类型
用pathinfo($filePath, PATHINFO_EXTENSION)获取后缀,转大写后映射:
'xlsx' → 'Xlsx','xls' → 'Xls'。
第四步:显式创建Reader,跳过样式节省内存
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$reader->setReadDataOnly(true);
逐行读取并过滤空行
方法一:用getRowIterator()遍历(推荐)
调用$worksheet->getRowIterator(),再对每行调用getCellIterator(),设置setIterateOnlyExistingCells(false)保证列数对齐。
方法二:用getHighestRow() + for循环(适合小文件)
先$highestRow = $worksheet->getHighestRow();再for($row = 2; $row
关键过滤逻辑:
每行读完后用array_filter($rowData)判断是否全为空值,【跳过全空行】,否则插入null会触发数据库NOT NULL约束失败。
字段映射与数据清洗
第一步:取第1行作为表头数组
$header = $worksheet->rangeToArray('A1:'.$highestColumn.'1')[0];
第二步:硬编码映射规则(示例)
将Excel中文列名转为数据库字段名:
['用户姓名' => 'user_name', '手机号' => 'mobile', '是否启用' => 'status']
第三步:转换特殊值
遇到“是/否”,转成1/0;日期单元格用$cell->getFormattedValue()或$cell->getCalculatedValue()避免时间戳错乱;文本型数字(如“00123”)用trim() + (string)保留前导零。
第四步:构建插入数据数组
foreach($dataRows as $row) {
$dbRow = [];
foreach($header as $i => $colName) {
$field = $map[$colName] ?? null;
if($field && isset($row[$i])) {
$dbRow[$field] = $this->cleanValue($row[$i]);
}
}
$insertData[] = $dbRow;
}
分批插入并开启事务
第一步:开启事务
$db = Db::connect();
$db->startTrans();
第二步:每500条一批插入
用array_chunk($insertData, 500)切块,每块调用Db::name('user')->insertAll($chunk)。
第三步:任一批失败则回滚
if (!$db->execute()) {
$db->rollback();
throw new Exception('批量插入中断,已回滚');
}
第四步:全部成功后提交
$db->commit();
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











