You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP ISBN生成器仅能单次写入数据库,重复存储失败求助

问题原因分析及解决方案

核心原因

  1. SQL注入引发的语法错误
    你的generate-isbn.php直接将用户输入的title和author拼接到INSERT语句中,如果输入内容包含单引号(如O'Neil),会破坏SQL语句结构,导致语法错误,插入失败。删除数据库记录后第一次输入的内容可能无特殊字符,所以能成功存储,后续输入带特殊字符的内容就会触发失败。

  2. ISBN字段唯一约束+竞态条件
    如果books表的isbn字段被设置了唯一约束,当多请求同时生成ISBN时会出现竞态问题:A请求检查ISBN不存在,B请求同时检查同一ISBN也不存在,A插入成功后,B插入就会因唯一约束冲突失败。即使单用户重复操作,若生成逻辑存在极小概率重复,也会触发该问题。

  3. 缺乏错误反馈机制
    代码未对数据库操作结果做校验,插入失败时无法返回错误信息,导致你无法直观得知存储失败的具体原因。

修复步骤

1. 用预处理语句防止SQL注入

修改generate-isbn.php的插入逻辑,使用mysqli预处理语句避免语法错误:

<?php
require "isbn.php";
header("Content-Type: application/json");

$title = $_POST["title"];
$author = $_POST["author"];
$isbn = generate_unique_isbn();

$conn = new mysqli("localhost", "root", "", "isbn");
// 预处理语句
$stmt = $conn->prepare("INSERT INTO books (isbn, title, author) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $isbn, $title, $author);
$stmt->execute();

// 检查插入结果
if ($stmt->affected_rows === 0) {
    echo json_encode(["error" => "存储失败:" . $conn->error, "isbn" => $isbn]);
} else {
    echo json_encode(["isbn" => $isbn]);
}

$stmt->close();
$conn->close();
?>

2. 修复ISBN校验位计算逻辑

原代码计算校验位时未跳过连字符,导致校验位计算错误,修改isbn.php的校验位计算部分:

function generate_unique_isbn() {
    do {
        $isbn = rand(100, 999) . "-";
        $isbn .= rand(0, 9) . "-";
        $isbn .= bin2hex(random_bytes(4)) . "-";

        // 跳过连字符计算校验位
        $check_digit = 0;
        $position = 0;
        for ($i = 0; $i < strlen($isbn); $i++) {
            $char = $isbn[$i];
            if ($char === '-') continue;
            $check_digit += $position % 2 === 0 ? (int)$char : 3 * (int)$char;
            $position++;
        }
        $check_digit = 10 - ($check_digit % 10);
        $check_digit = $check_digit === 10 ? 0 : $check_digit;
        $isbn .= $check_digit;

        $conn = new mysqli("localhost", "root", "", "isbn");
        $result = $conn->query("SELECT * FROM books WHERE isbn = '$isbn'");
        $conn->close();
    } while ($result && $result->num_rows > 0);

    return $isbn;
}

3. 添加强制错误检查

在数据库操作关键步骤添加错误判断,比如generate_unique_isbn中:

$conn = new mysqli("localhost", "root", "", "isbn");
if ($conn->connect_error) {
    die("数据库连接失败:" . $conn->connect_error);
}
$result = $conn->query("SELECT * FROM books WHERE isbn = '$isbn'");
if (!$result) {
    die("ISBN重复检查失败:" . $conn->error);
}

内容的提问来源于stack exchange,提问作者Gutsy Creatives

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:15:31