PHP执行插入操作时如何检查数据库中已存在的slug
嘿,这个需求在内容管理系统里太常见了!不管是检查slug还是其他需要唯一的字段,核心逻辑都是「先查询验证,再执行插入」,下面我给你分场景讲具体实现,都是生产环境能用的代码:
核心思路
在执行INSERT操作前,先对目标slug执行一次SELECT查询,确认它是否已经存在于数据库的对应表中:
- 如果存在:可以提示用户更换,或者自动生成带后缀的新slug
- 如果不存在:直接执行插入操作
基础实现(PDO版本,推荐)
PDO是PHP官方推荐的数据库操作方式,自带预处理语句能有效防止SQL注入,代码结构也更清晰:
// 先建立PDO连接(建议把这段封装成单独的工具类/函数) $dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8mb4'; $username = 'your_db_username'; $password = 'your_db_password'; try { $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 封装检查slug是否存在的函数 function slugExists($pdo, $slug) { // 用预处理语句避免注入风险 $stmt = $pdo->prepare("SELECT id FROM your_table WHERE slug = :slug LIMIT 1"); $stmt->bindParam(':slug', $slug, PDO::PARAM_STR); $stmt->execute(); // 有查询结果则说明slug已存在 return $stmt->rowCount() > 0; } // 实际插入流程 $targetSlug = "my-first-post"; $articleTitle = "我的第一篇测试文章"; if (slugExists($pdo, $targetSlug)) { echo "这个slug已经被占用啦!请更换一个,或者我可以帮你自动生成新的~"; // 这里可以直接调用下面的自动生成函数 } else { // 执行插入操作 $insertStmt = $pdo->prepare("INSERT INTO your_table (title, slug) VALUES (:title, :slug)"); $insertStmt->bindParam(':title', $articleTitle, PDO::PARAM_STR); $insertStmt->bindParam(':slug', $targetSlug, PDO::PARAM_STR); if ($insertStmt->execute()) { echo "文章插入成功!"; } else { echo "插入失败,请稍后重试。"; } }
MySQLi版本(面向对象写法)
如果你习惯用MySQLi,也可以用下面的实现:
// 建立MySQLi连接 $conn = new mysqli('localhost', 'your_db_username', 'your_db_password', 'your_database'); // 检查连接错误 if ($conn->connect_error) { die("数据库连接失败: " . $conn->connect_error); } $conn->set_charset("utf8mb4"); // 检查slug是否存在 function slugExists($conn, $slug) { $stmt = $conn->prepare("SELECT id FROM your_table WHERE slug = ? LIMIT 1"); $stmt->bind_param("s", $slug); $stmt->execute(); $stmt->store_result(); return $stmt->num_rows > 0; } // 插入流程 $targetSlug = "my-first-post"; $articleTitle = "我的第一篇测试文章"; if (slugExists($conn, $targetSlug)) { echo "Slug已被占用,请更换!"; } else { $stmt = $conn->prepare("INSERT INTO your_table (title, slug) VALUES (?, ?)"); $stmt->bind_param("ss", $articleTitle, $targetSlug); if ($stmt->execute()) { echo "插入成功!"; } else { echo "插入失败: " . $stmt->error; } } // 关闭连接 $conn->close();
进阶:自动生成唯一slug
如果不想让用户手动更换,我们可以写个函数自动生成带数字后缀的唯一slug:
function generateUniqueSlug($pdo, $baseSlug, $table = 'your_table') { $originalSlug = $baseSlug; $counter = 1; // 循环检查直到找到未被占用的slug while (slugExists($pdo, $baseSlug)) { $baseSlug = $originalSlug . "-" . $counter; $counter++; } return $baseSlug; } // 使用示例 $baseSlug = "my-first-post"; $uniqueSlug = generateUniqueSlug($pdo, $baseSlug); // 直接用$uniqueSlug执行插入即可
重要注意事项
- 必须使用预处理语句:绝对不能直接把变量拼进SQL字符串里,否则会有严重的SQL注入风险
- 并发场景处理:如果你的slug字段设置了
UNIQUE约束,极端情况下可能出现两个请求同时检查slug都不存在,然后同时插入导致报错的情况。这时候可以在插入时捕获异常,然后重新调用生成唯一slug的函数再尝试插入 - 提前处理slug:建议先把标题转成标准slug格式(比如转小写、替换特殊字符为横线、去除空格等),这个可以单独写个
generateSlug($title)函数
内容的提问来源于stack exchange,提问作者Sandeep
相关产品推荐
相关产品推荐

