求助:将Mysqli删除父类及子类代码转为PDO时遇问题
嘿,我来帮你把这段删除父类及子类的MySQLi代码转换成PDO实现,同时梳理清楚关键细节,避免踩坑~
首先先补全你提到的那段可正常运行的MySQLi示例代码(根据常见逻辑补全):
// Delete if(isset($_GET['delete']) && !empty($_GET['delete'])) { $delete_id = (int)$_GET['delete']; $delete_id = sanitize($delete_id); /* Deleting a parent and its children */ // 查询所有一级子类ID $get_children = $db->query("SELECT id FROM categories WHERE parent = '$delete_id'"); // 循环删除子类 while($child = mysqli_fetch_assoc($get_children)){ $db->query("DELETE FROM categories WHERE id = '{$child['id']}'"); } // 删除父类 $db->query("DELETE FROM categories WHERE id = '$delete_id'"); header('Location: categories.php'); exit(); }
转换后的PDO实现方案
首先确保你已经正确建立了PDO连接(示例连接代码如下,记得替换成你的数据库信息):
$pdo = new PDO( "mysql:host=localhost;dbname=your_database;charset=utf8mb4", "your_username", "your_password", [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 开启异常模式,方便错误处理 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // 默认关联数组返回 ] );
然后是核心的删除逻辑:
// 处理删除请求 if (isset($_GET['delete']) && !empty($_GET['delete'])) { $delete_id = (int)$_GET['delete']; // 这里的sanitize针对整数来说,(int)强制转换已经足够安全,PDO预处理会进一步加固 try { // 开启事务!保证删除操作原子性:要么父类+子类全删,要么全不删,避免孤儿数据 $pdo->beginTransaction(); // 方案1:仅删除一级子类(对应原MySQLi逻辑) // 先删子类 $deleteChildren = $pdo->prepare("DELETE FROM categories WHERE parent = :delete_id"); $deleteChildren->bindParam(':delete_id', $delete_id, PDO::PARAM_INT); $deleteChildren->execute(); // 再删父类 $deleteParent = $pdo->prepare("DELETE FROM categories WHERE id = :delete_id"); $deleteParent->bindParam(':delete_id', $delete_id, PDO::PARAM_INT); $deleteParent->execute(); // -------------------------- // 方案2:删除所有层级的子类(多级树形结构适用) // 用MySQL递归CTE一次性删除父类+所有子/孙类,效率更高 // $deleteAll = $pdo->prepare(" // WITH RECURSIVE category_tree AS ( // SELECT id FROM categories WHERE id = :delete_id // UNION ALL // SELECT c.id FROM categories c // JOIN category_tree ct ON c.parent = ct.id // ) // DELETE FROM categories WHERE id IN (SELECT id FROM category_tree) // "); // $deleteAll->bindParam(':delete_id', $delete_id, PDO::PARAM_INT); // $deleteAll->execute(); // -------------------------- // 提交事务 $pdo->commit(); // 跳转回分类列表页 header('Location: categories.php'); exit(); } catch (PDOException $e) { // 出错就回滚所有操作 $pdo->rollBack(); // 开发环境可以输出错误,生产环境建议写日志不要直接暴露 die("删除操作失败:" . $e->getMessage()); } }
几个关键细节说明
- 事务处理:这是原MySQLi代码里缺失的重要环节!如果删除子类时出错,原代码会导致父类被删除但子类残留,用
beginTransaction()+commit()+rollBack()可以彻底避免这种情况。 - 预处理语句:PDO的
prepare()和bindParam()从根源上防止SQL注入,比MySQLi直接拼接SQL安全得多,指定PDO::PARAM_INT还能明确参数类型,进一步降低风险。 - 多级子类支持:如果你的分类是多级树形(比如子类还有子类),直接用递归CTE的方案更高效,不用循环查询,一次SQL就能搞定所有关联记录的删除。
- 错误处理:PDO的异常模式能帮你快速定位问题,生产环境记得把错误信息写入日志,不要直接输出给用户。
内容的提问来源于stack exchange,提问作者Lortnok
相关产品推荐
相关产品推荐

