PHP+MySQL批量校验车辆检查记录 解决邮件重复发送问题
问题根因
你现在遇到的重复发信问题属于典型的逻辑设计错误,核心问题有3个:
- 判断逻辑完全倒置:你逐行遍历已存在的检查记录,每读到一条记录,就对所有硬编码的车牌做不等判断——只要当前行的车牌不是某个目标车牌,就立刻发一封提醒邮件。假设表里有1条检查记录,你就会给剩下6个车牌各发1封;表里有10条历史记录,就会发60封完全重复的邮件。
- SQL语句无效且无时间过滤:你写的
SELECT Registration FROM vehiclecheck WHERE ID_carcheck缺少WHERE判断条件,会拉取表中所有历史检查记录,根本没有只筛选当月提交的数据。 - 发信逻辑冗余:你在循环内重复初始化PHPMailer实例、重复配置相同的发信参数,每发一封邮件就新建一次SMTP连接,性能极差。
优化方案
把逐行触发的判断逻辑改成批量对比:
- 先维护所有需要完成月度检查的车辆车牌清单
- 用SQL一次性查询当月已提交检查的去重车牌列表
- 对比两个清单,差集就是当月未完成检查的车辆;仅当存在未完成记录时,才初始化一次邮件实例,把所有缺失记录汇总到正文,只发1次提醒邮件。
优化后的可直接运行代码如下:
<?php session_start(); // 数据库连接 $conn = mysqli_connect("localhost", "Username", "Password", "Database"); if (!$conn) { die("数据库连接失败: " . mysqli_connect_error()); } require("PHPMailer/src/PHPMailer.php"); require("PHPMailer/src/SMTP.php"); // 1. 配置所有需要校验的在册车辆车牌,后续新增车辆直接加在这个数组里就行 $requiredRegistrations = ["267AD7", "244XST", "572ZKK", "072TVX", "348ZVB", "066XXM", "063ZCD"]; $completedRegistrations = []; // 2. 查询当月已完成检查的车牌,注意把check_date替换成你表里实际存储检查提交时间的字段名 // 加DISTINCT是防止同一车辆当月多次上传记录导致重复统计 $query = "SELECT DISTINCT Registration FROM vehiclecheck WHERE YEAR(check_date) = YEAR(CURDATE()) AND MONTH(check_date) = MONTH(CURDATE())"; $queryRun = mysqli_query($conn, $query); if ($queryRun) { while ($row = mysqli_fetch_assoc($queryRun)) { $completedRegistrations[] = $row["Registration"]; } } // 3. 计算差集:需要检查但没在当月完成列表里的车牌 $missingRegistrations = array_diff($requiredRegistrations, $completedRegistrations); // 没有缺失记录直接终止,不发邮件 if (empty($missingRegistrations)) { exit; } // 4. 存在缺失记录,只初始化一次邮件实例,发送汇总提醒 $mail = new PHPMailer\PHPMailer\PHPMailer(); $mail->IsSMTP(); $mail->SMTPDebug = 0; // 定时任务运行关闭调试输出,需要排查问题再改成1 $mail->SMTPAuth = true; $mail->SMTPSecure = 'ssl'; $mail->Host = "atqldhub.com.au"; $mail->Port = 465; $mail->IsHTML(true); $mail->Username = "info@atqldhub.com.au"; $mail->Password = "5%226}Mh@Cdb"; $mail->SetFrom("info@atqldhub.com.au"); $mail->Subject = "月度车辆检查未完成提醒"; // 拼接所有未完成的车牌到正文 $missingList = implode("、", $missingRegistrations); $mail->Body = "以下车辆当月未完成例行检查,请尽快跟进:<br>" . $missingList; $mail->AddAddress("alex.crabtree@atqld.com.au"); $mail->send(); mysqli_close($conn); ?>
额外优化建议
- 如果你的车辆清单是存在独立的车辆信息表中,不要硬编码
$requiredRegistrations数组,直接从车辆表查询所有有效在册车牌即可,后续新增、报废车辆不需要改代码。 - 如果检查记录存储的是unix时间戳而非datetime类型,把SQL里的时间筛选条件改成对应时间戳范围判断即可,确保只统计当月提交的有效记录。
- 可以给定时任务加执行时间窗口,比如每月25号到月底每天执行一次,非检查周期不运行,避免发送无效提醒。
内容的提问来源于stack exchange,提问作者Mnuemonix
相关产品推荐
相关产品推荐

