Excel模板表头必须严格匹配“姓名、学号、手机号、家长姓名、关系”5列同名且顺序固定;学号需转字符串后用ctype_digit()校验,手机号须清洗再正则校验并查重;读取时设setReadDataOnly(true),日期用excelToDateTimeObject转换;所有字段入库前预处理防SQL注入和XSS。

Excel模板结构必须严格匹配字段名和顺序
PHP 导入班级通信录时,校验失败多数源于 Excel 表头与代码预设不一致。不是“差不多就行”,而是 姓名、学号、手机号、家长姓名、关系 这 5 列必须**完全同名且顺序固定**(通常首行为表头,第 2 行起为数据)。若用户上传了 姓名 写成 学生姓名 或列顺序是 学号→姓名→手机号,PhpSpreadsheet 读取后字段会错位,后续校验全失效。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 在导入页面明确展示模板下载链接,并附带截图标注必填列名和顺序
- 读取 Excel 后立即用
$worksheet->getRowIterator(1, 1)->current()取第一行,逐单元格比对['姓名', '学号', '手机号', '家长姓名', '关系'] - 发现任一列名不匹配,直接返回错误:
"模板表头错误:第X列应为'手机号',实际为'联系电话'"
学号和手机号需做格式+唯一性双重校验
仅用 is_numeric() 判定学号会放过 123.0 或科学计数法(如 1E+06);仅用正则 /^1[3-9]\d{9}$/ 校验手机号,会漏掉带空格或短横线的合法输入(如 138 1234 5678)。更关键的是:单条记录校验通过不等于整批可用——同一 Excel 中出现重复学号,会导致数据库插入冲突或覆盖旧记录。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 学号统一转字符串处理,用
trim()去空格后,再用ctype_digit()判定纯数字,长度按学校规则限制(如 8–10 位) - 手机号先
preg_replace('/[\s\-()]+/', '', $phone)清洗,再用正则校验,最后检查是否已存在于本次待导入数组中(用array_column($data, '学号')提前去重并报重复项) - 所有校验失败项必须原样返回行号和错误原因,例如:
"第5行:手机号格式错误(138xxxxx)"
使用 PhpSpreadsheet 时避免内存溢出和日期解析异常
班级通信录 Excel 若含合并单元格、隐藏行、自定义样式,PhpSpreadsheet 默认加载会吃光内存;更隐蔽的问题是 Excel 里“2023/9/1”这类日期,在 PHP 中可能被读成数字(如 45170),直接 (string)$cellValue 输出会变成乱码。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 初始化读取器时强制设置
$reader->setReadDataOnly(true),跳过样式、公式、合并单元格 - 对疑似日期列(如“入学日期”),用
PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cellValue)转换,捕获Exception并提示“第X行日期格式不支持” - 大文件(>500 行)启用分块读取:
$reader->setReadFilter(new ChunkReadFilter()),每次只处理 200 行
校验通过后仍要防 SQL 注入和 XSS 输出
很多人以为校验完 Excel 就安全了,但没意识到:如果把未过滤的 家长姓名 字段直接拼进 SQL 或输出到 HTML 页面,攻击者在 Excel 单元格里填 O'Reilly 或 ,就会触发问题。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 入库前对所有字符串字段调用
mysqli_real_escape_string()(或更推荐 PDO 预处理) -
前端展示导入结果时,用
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')转义,尤其家长姓名和关系字段 - 日志记录原始数据时,也要先脱敏,避免敏感信息泄露到 error_log
最容易被忽略的是:校验逻辑写在前端 JavaScript 里,后端不做二次检查——Excel 文件可绕过前端直接 POST,所有校验必须在 PHP 层完整执行一遍。











