PHP中提交单表单时如何将主表自增主键作为第二表外键同步插入
实现逻辑
整个需求的核心流程非常明确:先写入主表拿到自增主键,再将该主键作为外键写入任务表即可,全程需要搭配事务保证两张表的数据一致性,避免出现主表写入成功但任务表写入失败的脏数据。
前置库表准备
首先确认你的两张表结构符合关联要求,任务表必须存在用于关联主表主键的外键字段,参考建表语句如下:
-- 维保主表:存储通用信息 CREATE TABLE maintenance_records ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '主表主键', record_date DATE NOT NULL COMMENT '维保日期', record_time TIME NOT NULL COMMENT '维保时间', technician VARCHAR(50) NOT NULL COMMENT '技术人员', department VARCHAR(50) NOT NULL COMMENT '所属部门', location VARCHAR(100) NOT NULL COMMENT '维保位置', suggestion TEXT COMMENT '维保建议', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 维保任务表:存储具体任务 CREATE TABLE maintenance_tasks ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '任务表主键', maintenance_id INT UNSIGNED NOT NULL COMMENT '关联主表ID的外键', task_content VARCHAR(100) NOT NULL COMMENT '具体任务内容', -- 可按需添加任务耗时、完成状态等额外字段 FOREIGN KEY (maintenance_id) REFERENCES maintenance_records(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
具体实现代码
原生PDO实现(通用版本)
适合没有用框架或者自研MVC框架的场景,自带事务、预处理逻辑,可直接复用:
<?php // 表单校验通过后,先拿到结构化的表单数据 $mainData = [ 'record_date' => $_POST['record_date'], 'record_time' => $_POST['record_time'], 'technician' => $_POST['technician'], 'department' => $_POST['department'], 'location' => $_POST['location'], 'suggestion' => $_POST['suggestion'] ?? '' ]; // 前端任务用数组格式提交(比如name="tasks[]"),直接接收即可 $taskList = $_POST['tasks'] ?? []; try { // 初始化PDO连接,替换为你自己的数据库配置 $pdo = new PDO('mysql:host=127.0.0.1;dbname=你的库名;charset=utf8mb4', '数据库账号', '数据库密码'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 开启事务,确保两张表要么全部写入成功,要么全部回滚 $pdo->beginTransaction(); // 第一步:写入主表数据 $mainSql = "INSERT INTO maintenance_records (record_date, record_time, technician, department, location, suggestion) VALUES (?, ?, ?, ?, ?, ?)"; $mainStmt = $pdo->prepare($mainSql); $mainStmt->execute(array_values($mainData)); // 获取刚插入的主表自增ID $mainRecordId = $pdo->lastInsertId(); // 第二步:批量写入任务表,自动关联主表ID $taskSql = "INSERT INTO maintenance_tasks (maintenance_id, task_content) VALUES "; $taskParams = []; foreach ($taskList as $taskContent) { $taskSql .= "(?, ?),"; $taskParams[] = $mainRecordId; $taskParams[] = trim($taskContent); } // 去除最后多余的逗号 $taskSql = rtrim($taskSql, ','); $taskStmt = $pdo->prepare($taskSql); $taskStmt->execute($taskParams); // 所有操作成功,提交事务 $pdo->commit(); // 这里可以加你的业务后续逻辑,比如跳转、返回成功提示 } catch (Exception $e) { // 任何一步出错,回滚所有操作 $pdo->rollBack(); // 这里可以加你的错误处理逻辑 die("提交失败:" . $e->getMessage()); } ?>
常用MVC框架快捷实现
主流框架都已经封装了自增ID获取、批量插入的方法,代码更简洁:
- Laravel 框架示例:
// 写入主表并返回主键ID $mainId = MaintenanceRecord::insertGetId($mainData); // 组装任务数据 $taskData = collect($taskList)->map(fn($task) => [ 'maintenance_id' => $mainId, 'task_content' => trim($task) ])->toArray(); // 批量插入任务表 MaintenanceTask::insert($taskData);
- ThinkPHP 框架示例:
// 写入主表并返回主键ID $mainId = Db::name('maintenance_records')->insertGetId($mainData); // 组装任务数据 $taskData = []; foreach ($taskList as $task) { $taskData[] = [ 'maintenance_id' => $mainId, 'task_content' => trim($task) ]; } // 批量插入任务表 Db::name('maintenance_tasks')->insertAll($taskData);
注意事项
- 前端任务字段用数组格式命名即可,比如多选框
<input type="checkbox" name="tasks[]" value="扫地"> 扫地,输入框<input type="text" name="tasks[]" placeholder="输入自定义任务">,后端直接接收$_POST['tasks']就是数组格式 - 所有用户提交的数据必须做校验,比如必填字段判空、格式校验,避免非法数据入库
- 预处理语句已经规避了SQL注入风险,不要直接拼接用户输入到SQL语句中
内容的提问来源于stack exchange,提问作者Shelvin
相关产品推荐
相关产品推荐

