PHP删除数据库对象后Select选项不更新且报非对象属性提示
解决删除后选项不更新及Notice错误的问题
让我们一步步解决你的问题:
1. 先解决 "Trying to get property of non-object" 的Notice错误
这个错误的核心原因是:执行mysqli_multi_query后,数据库连接中残留了未处理的结果集,导致后续的$conn->query($sql)执行失败,返回false(不是对象),但你直接尝试访问$prove_result->num_rows,因此触发了Notice。
另外,你的代码存在SQL注入风险——直接将用户输入的$spmId拼接到SQL语句中,这是非常危险的,必须改用预处理语句来规避。
修改删除逻辑:
替换原来的multi_query代码,改用预处理语句分别执行两个DELETE操作,同时避免结果集阻塞:
if(isset($_POST['slettSpm'])){ // 先验证并过滤输入,确保spmId是整数 $spmId = filter_input(INPUT_POST, 'spmId', FILTER_VALIDATE_INT); if($spmId){ // 删除alternativ表中的关联记录(预处理语句防注入) $stmt = $conn->prepare("DELETE FROM `alternativ` WHERE `SpormalId` = ?"); $stmt->bind_param("i", $spmId); // "i"表示参数为整数类型 $stmt->execute(); $stmt->close(); // 删除sporsmal表中的主记录 $stmt = $conn->prepare("DELETE FROM `sporsmal` WHERE `SporsmalId` = ?"); $stmt->bind_param("i", $spmId); $stmt->execute(); $stmt->close(); } // 关键操作:删除完成后重定向到当前页面 // 既可以避免表单重复提交,又能强制刷新数据库数据 header("Location: " . $_SERVER['PHP_SELF']); exit(); // 必须exit,防止后续代码继续执行 }
2. 解决删除后Select选项不更新的问题
当前代码在删除后直接在POST请求中生成页面,但由于浏览器缓存或连接状态异常,查询可能无法获取最新的数据库数据。使用上面的header("Location: ...")重定向,会触发一个GET请求重新加载页面,此时代码会重新查询数据库,自然会显示剩余的选项,不需要手动刷新。
3. 加固查询逻辑,避免潜在错误
在查询sporsmal列表时,先检查查询结果是否有效,防止再次出现non-object的Notice:
$sql = "SELECT * FROM sporsmal WHERE ProveId = $id"; $prove_result = $conn->query($sql); // 先确认$prove_result是有效对象,再访问num_rows if($prove_result && $prove_result->num_rows > 0) { while($row = $prove_result->fetch_assoc()){ $sporsmal = htmlspecialchars($row["Sporsmal"]); // 转义输出,防止XSS攻击 $sporsmalId = $row["SporsmalId"]; echo "<option value='$sporsmalId'>$sporsmal</option>"; } } else { // 没有数据时给用户友好提示 echo "<option value=''>Ingen spørsmål tilgjengelig</option>"; }
额外建议:
- 始终验证和过滤用户输入:比如用
filter_input确保spmId是整数,避免非法值传入数据库。 - 开发环境开启错误提示:在代码开头加上
error_reporting(E_ALL); ini_set('display_errors', 1);,方便快速定位问题。 - 对输出内容进行转义:比如用
htmlspecialchars处理用户输入的文本,防止XSS攻击。
修改后的完整关键代码片段:
<?php // 开发环境开启错误提示 error_reporting(E_ALL); ini_set('display_errors', 1); session_start(); // 确保session已启动 if(isset($_POST['endreProve']) || isset($_POST['slettSpm'])){ if(isset($_POST['slettSpm'])){ $spmId = filter_input(INPUT_POST, 'spmId', FILTER_VALIDATE_INT); if($spmId){ $stmt = $conn->prepare("DELETE FROM `alternativ` WHERE `SpormalId` = ?"); $stmt->bind_param("i", $spmId); $stmt->execute(); $stmt->close(); $stmt = $conn->prepare("DELETE FROM `sporsmal` WHERE `SporsmalId` = ?"); $stmt->bind_param("i", $spmId); $stmt->execute(); $stmt->close(); } header("Location: " . $_SERVER['PHP_SELF']); exit(); } if(isset($_POST['endreProve'])){ $id = $_POST['endreProve']; $id2 = explode('- ', $id); $_SESSION['proveId'] = $id2[1]; header("Location: " . $_SERVER['PHP_SELF']); exit(); } } // 确保proveId存在,避免空值导致SQL错误 $id = isset($_SESSION['proveId']) ? $_SESSION['proveId'] : ''; if(empty($id)){ // 如果没有选中考试,跳转到选择页面 header("Location: VelgProve.php"); exit(); } ?> <form style="padding-left: 30px; padding-top: 15px;" action="Rediger.php" method="POST"> <div class='form-group row'> <div class='col-sm-12'> <h2><b> Prøve <?php echo $id ?> </b></h2> <label>Velg spørsmål:</label> <select name="spmId"> <?php $sql = "SELECT * FROM sporsmal WHERE ProveId = $id"; $prove_result = $conn->query($sql); if($prove_result && $prove_result->num_rows > 0) { while($row = $prove_result->fetch_assoc()){ $sporsmal = htmlspecialchars($row["Sporsmal"]); $sporsmalId = $row["SporsmalId"]; echo "<option value='$sporsmalId'>$sporsmal</option>"; } } else { echo "<option value=''>Ingen spørsmål tilgjengelig</option>"; } ?> </select> <input type='submit' class='btn btn-primary btn-sm' name='endreSpm' value='Endre'> <input type='submit' class='btn btn-danger btn-sm' name='slettSpm' value='Slett'><br/><br/> <!-- 剩余表单内容保持不变 --> <label><b>Legg til spørsmål</b></label><br/> <!-- ... 其他表单代码 ... --> </div> </div> </form>
这样修改后,删除操作完成后会自动刷新页面,Select选项会显示最新的剩余内容,同时Notice错误也会消失,还大幅提升了代码的安全性。
内容的提问来源于stack exchange,提问作者Devran Akat
相关产品推荐
相关产品推荐

