
本文详解如何将形如“Category SubCategory SubSubCategory”的反斜杠分隔字符串,逐层插入数据库并自动建立父子关系(parent_id 指向其直接上级ID),关键在于利用 PDO 的 lastInsertId() 动态获取刚插入记录的自增主键。
本文详解如何将形如“category subcategory subsubcategory”的反斜杠分隔字符串,逐层插入数据库并自动建立父子关系(parent_id 指向其直接上级id),关键在于利用 pdo 的 `lastinsertid()` 动态获取刚插入记录的自增主键。
在构建多级分类系统时,常需将层级化文本(如 "A B C")解析为树状结构并持久化到数据库。核心挑战在于:后一级分类的 parent_id 必须等于前一级插入记录的自增主键(id),而非固定值 0。原始代码中所有记录均设 parent_id = 0,导致无法形成真实层级。
正确的实现需满足三点:
- 安全执行 SQL:使用预处理语句防止 SQL 注入;
- 动态关联父级:每插入一条记录后,立即捕获其 id,作为下一条记录的 parent_id;
- 顺序严格保证:按从左到右(顶层→底层)顺序插入,确保父节点先于子节点存在。
以下是推荐的完整实现:
$cats = "Category \ SubCategory \ SubSubCategory"; // 注意:PHP 中需双反斜杠转义
$categories = array_map('trim', explode('\', $cats)); // 自动去除首尾空格
$stmt = $db->prepare("INSERT INTO `cat` (`name`, `parent_id`) VALUES (:name, :parent)");
$stmt->bindParam(':name', $category, PDO::PARAM_STR);
$stmt->bindParam(':parent', $parent, PDO::PARAM_INT);
$parent = 0; // 顶层分类的 parent_id 为 0
foreach ($categories as $category) {
$stmt->execute();
$parent = $db->lastInsertId(); // 获取刚插入记录的 id,作为下一级的 parent_id
}
✅ 关键说明:
- array_map('trim', ...) 确保 SubCategory 前后无空格(避免因空格导致名称重复或查询异常);
- 使用 PDO::PARAM_INT 绑定 $parent,保障数据类型安全;
- lastInsertId() 必须在每次 execute() 后立即调用,否则可能被后续插入覆盖;
- 此逻辑隐含前提:表 cat 的 id 字段为 AUTO_INCREMENT PRIMARY KEY,且数据库驱动支持该方法(MySQL、PostgreSQL 等主流驱动均支持)。
⚠️ 注意事项:
- 若需支持同一层级多个同名分类(如不同父级下的同名子类),当前设计已兼容;但若业务要求全局唯一名称,应额外添加唯一索引或校验逻辑;
- 生产环境建议增加异常处理(如 try...catch),并在事务中执行整组插入,确保原子性;
- 反斜杠 在 PHP 字符串中是转义字符,定义原始字符串时务必写成 "A \ B" 或使用单引号 'A B'。
通过该方案,输入 "Category \ SubCategory \ SubSubCategory" 将准确生成如下数据库状态:
| id | name | parent_id |
|----|------------------|-----------|
| 1 | Category | 0 |
| 2 | SubCategory | 1 |
| 3 | SubSubCategory | 2 |
层级关系清晰、可扩展,为后续递归查询、路径生成等操作奠定坚实基础。










