php实现班级通信录导入日志追踪_php记录导入过程日志【步骤】

8次阅读

应使用结构化数据库表(如import_logs)替代文本日志,字段需含import_id、status、时间戳、计数器及TEXT型log_message,并实时分批更新、保留上下文、加索引与清理策略。

php实现班级通信录导入日志追踪_php记录导入过程日志【步骤】

导入前先创建结构化日志记录表

直接往文本文件里追加日志容易丢行、乱序、难排查,尤其并发导入或大文件分批处理时。建议用数据库表存日志,字段至少包含:import_id(唯一批次号)、file_namestatus(pending/running/success/failed)、start_timeend_timeprocessed_counterror_countlog_message(TEXT 类型,存关键错误或跳过行信息)。

示例建表语句:

CREATE TABLE import_logs (   id INT AUTO_INCREMENT PRIMARY KEY,   import_id VARCHAR(32) NOT NULL,   file_name VARCHAR(255),   status ENUM('pending','running','success','failed') DEFAULT 'pending',   start_time DATETIME,   end_time DATETIME,   processed_count INT DEFAULT 0,   error_count INT DEFAULT 0,   log_message TEXT,   created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
  • import_id 建议用 uniqid('imp_')md5($_FILES['file']['name'] . time()) 生成,确保同文件多次导入可区分
  • 不要把整条学生数据 jsON 化塞进 log_message,只记关键上下文,比如“第127行:手机号格式错误(138xxxx999)”
  • 避免在循环内频繁 INSERT,可先收集错误行,最后批量写入一条日志记录

excel 解析时实时写入中间态日志

phpSpreadsheet 读取时,别等全量解析完再记日志——万一卡在第 5000 行,前面的进度就丢了。应在每处理 N 行(如 100 行)或检测到异常时,更新一次数据库中的 processed_countlog_message

关键代码片段:

立即学习PHP免费学习笔记(深入)”;

$importId = uniqid('imp_'); $pdo->prepare("INSERT INTO import_logs (import_id, file_name, status, start_time) VALUES (?, ?, 'running', NOW())")->execute([$importId, $fileName]);  // 处理循环中 foreach ($rows as $index => $row) {   if ($index % 100 === 0 && $index > 0) {     $pdo->prepare("UPDATE import_logs SET processed_count = ?, log_message = CONCAT(log_message, ?) WHERE import_id = ?")       ->execute([$index, "n[INFO] 已处理 {$index} 行", $importId]);   }   // ……校验、入库逻辑   if ($validationFailed) {     $errorLog = "[ERROR] 第{$index}行:{$errorMessage}";     $pdo->prepare("UPDATE import_logs SET error_count = error_count + 1, log_message = CONCAT(log_message, ?) WHERE import_id = ?")       ->execute([$errorLog, $importId]);   } }
  • CONCAT(log_message, ?) 而非覆盖,保留时间线顺序
  • 避免在事务内做大量日志更新,否则拖慢主流程;可将日志写入设为非事务性(如用另一 pdo 连接)
  • 若用 fputcsv 写文件日志,务必加 fflush(),否则缓冲区未刷盘就中断,日志就断在半截

导入失败后能准确定位并重试

用户传了个 2000 行 Excel,报错“第 883 行导入失败”,但没留原始行内容和错误,根本没法复现。必须让日志带上下文。

  • 捕获 try/catch 中的 ExceptionPDOException,用 $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine() 记入 log_message
  • 对每一行学生数据,生成临时数组包含原始单元格值(如 ['name' => '张三', 'phone' => '138xxx']),出错时 json_encode($rawRow) 一并记下
  • 提供「按 import_id 查看完整日志」接口前端渲染成折叠式列表,支持复制某行原始数据用于调试
  • 不建议自动重试——网络超时可重试,但“身份证重复”这种业务错误重试只会再错一遍

日志权限与清理策略不能忽略

日志表会越积越大,尤其测试环境反复上传。线上跑一个月,import_logs 可能达百万行,查起来卡,备份也慢。

  • 给日志表加联合索引:KEY idx_import_status_time (import_id, status, created_at),方便按批次+状态快速检索
  • 设置定时任务(如每天凌晨)清理 90 天前的 status = 'success' 记录,保留 failed 至少 180 天
  • log_message 字段别设太小(至少 TEXT),但也要防恶意超长输入——入库前用 mb_strimwidth($msg, 0, 2000, '...') 截断
  • 日志内容可能含手机号、姓名等敏感字段,导出或查看接口必须走登录鉴权,且禁止前端直接 echo $log_message,要 html 转义

真正难的不是记日志,是让日志在出问题时能一句话告诉你“谁、什么时候、对哪个文件、卡在哪一行、为什么卡”。字段设计、更新时机、上下文保全,这三处漏掉任何一环,日志就只剩占磁盘空间的份儿了。

text=ZqhQzanResources