
本文详解如何通过数据库状态校验与 php 逻辑控制,确保每本图书(以 jalad 标识)必须完整录入 5 页(sanad)后才允许插入新书,防止数据不完整导致的业务逻辑断裂。
本文详解如何通过数据库状态校验与 php 逻辑控制,确保每本图书(以 `jalad` 标识)必须完整录入 5 页(`sanad`)后才允许插入新书,防止数据不完整导致的业务逻辑断裂。
在图书管理系统中,若每本书严格对应且仅限 5 个页面(如古籍影印中的“页码”或档案卷宗中的“条目”),则数据库设计需配合强业务约束:不允许存在页数 。原始代码存在多个关键缺陷:未区分不同书籍(仅用 x 字段计数,但未关联 jalad)、sql 注入风险、逻辑分支错位(
以下是经过重构的健壮实现方案:
✅ 核心逻辑三步走
- 识别当前操作的图书:从 $_POST[‘jalad’] 获取书名(替代原代码中模糊的 x);
- 查询该书已存页数:select count(*) FROM books WHERE jalad = ?;
- 按状态决策:
- 若计数为 0 → 首次插入,允许;
- 若计数在 1–4 之间 → 继续插入同书页,允许;
- 若计数为 5 → 该书已完成,拒绝新页;
- 若计数 > 5 → 数据异常,应告警(非正常路径)。
✅ 安全、可运行的 PHP 示例(SQL Server + pdo/SQLSRV)
<?php $serverName = "your_server"; $database = "your_db"; $connectionInfo = ["Database" => $database]; $conn = sqlsrv_connect($serverName, $connectionInfo); if (!$conn) { die("Connection failed: " . print_r(sqlsrv_errors(), true)); } // ✅ 使用明确字段:jalad(书名)和 sanad(页内容) $bookName = trim($_POST['jalad'] ?? ''); $pageContent = $_POST['sanad'] ?? ''; if (empty($bookName)) { die("Error: Book name (jalad) is required."); } // ✅ 参数化查询防注入 $sqlCount = "SELECT COUNT(*) AS page_count FROM books WHERE jalad = ?"; $params = [$bookName]; $stmt = sqlsrv_query($conn, $sqlCount, $params); if (!$stmt) { die("Count query failed: " . print_r(sqlsrv_errors(), true)); } $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $currentPageCount = (int)$row['page_count']; // ✅ 状态判断与插入 if ($currentPageCount >= 5) { echo "This book '{$bookName}' already has 5 pages. Please start a new book."; } elseif ($currentPageCount < 5) { $insertSql = "INSERT INTO books (jalad, sanad) VALUES (?, ?)"; $insertParams = [$bookName, $pageContent]; if (sqlsrv_query($conn, $insertSql, $insertParams)) { $newCount = $currentPageCount + 1; echo "Page {$newCount}/5 saved for '{$bookName}'."; } else { echo "Insert failed: " . print_r(sqlsrv_errors(), true); } } else { // 理论上不会进入此分支(count 不可能为负) echo "Unexpected database state."; } ?>
⚠️ 关键注意事项
- 字段语义清晰化:务必使用 jalad(书名)作为分组依据,而非通用字段 x,否则无法区分不同书籍;
- 禁止拼接 SQL:原始代码中 $sql = “… WHERE x=’$x'” 极易引发 SQL 注入,必须改用参数化查询;
- 事务增强一致性(进阶推荐):若插入页数需原子性(如同时更新计数器表),应包裹在 sqlsrv_begin_transaction() 内;
- 前端协同校验:在 HTML 表单中禁用“提交新书”按钮,直到当前书页数达 5,提升用户体验并减少无效请求;
- 唯一约束辅助:可在数据库添加 UNIQUE(jalad, sanad) 或触发器,防止重复页,但主控逻辑仍在应用层。
通过以上设计,系统将严格遵循“5页封顶、填满才准入新书”的业务规则,既保障数据完整性,又具备良好的可维护性与安全性。