我有一个模型方法,在执行时总是返回true。即使我给它一个随机的id号码,但不会在我的数据库中退出
我的模型方法
public function updateSetting($data, $id)
{
$con = new Database();
$insert = $con->mysqli->prepare('UPDATE `settings` SET `value` = ? WHERE `id` = ?');
$insert->bind_param('ss', $data, $id);
if ($insert->execute()) {
return true;
} else {
return false;
}
}
我的控制器方法
public function updatePasswordSetting()
{
if (isset($_POST['pw_setting'])) {
$strong_pw = 1;
} else {
$strong_pw = null;
}
if (!$this->settings_model->updateSetting($strong_pw, 'asdf')) {
exit('Could not update password setting');
}
}
在上面的方法中,我给updateSetting控制器方法一个无意义的参数,比如'asdf',即使我的设置表中没有这样的id,方法仍然返回true。
发生了什么事?
答案 0 :(得分:1)
这是正常行为。如果execute()
返回true
,则这意味着执行语句时没有SQL代码/数据库/网络错误。如果没有记录受到语句的影响,不将其视为错误是很自然的。
正如@SearchAndResQ建议的那样,您可以检查受影响的行。但请注意,这有其注意事项,因此您应首先阅读MySQL的ROW_COUNT() documentation和mysql_affected_rows() documentation(其中一个必须由PHP在幕后使用)。
值得注意的是,UPDATE
的行为取决于建立与数据库的连接时设置的标志,并且REPLACE
和ON DUPLICATE KEY UPDATE
可能会出现意外行为。
就个人而言,在这种情况下我更喜欢另一种方法。我首先SELECT
有问题的记录FOR UPDATE
,然后查看结果集以检查是否有任何记录受到影响。然后我在记录仍然被锁定时进行更新。你需要使用交易(我正在做的事情,所以额外的努力也不算太糟糕)。
恕我直言,该方法更具可移植性,其结果更易理解,因此通常比affected_rows
机制更安全。它的缺点是你需要使用事务并且它可能更慢。
答案 1 :(得分:0)
只有在出现严重的数据库错误时才会发生这种情况。但是在这种情况下,在发生错误的特定操作的详细信息中没有意义。如果出现严重的数据库错误,则只显示通用的服务器错误页面。
另一方面,作为程序员,您必须才能知道,在更新过程中发生了什么特定错误,以便能够修复它。而且您的代码无助于您。
我写了一篇文章PHP error reporting basics来解释这些东西。为了使你的代码正确,只需删除两个函数中的所有结果检查条件
public function updateSetting($con, $data, $id)
{
$insert = $con->mysqli->prepare('UPDATE `settings` SET `value` = ? WHERE `id` = ?');
$insert->bind_param('ss', $data, $id);
$insert->execute();
}
public function updatePasswordSetting()
{
if (isset($_POST['pw_setting'])) {
$strong_pw = 1;
} else {
$strong_pw = null;
}
$this->settings_model->updateSetting($strong_pw, 'asdf');
}
然后编写错误处理程序或全局try catch以显示通用服务器错误页面。
您可能已经注意到,您也不应该在每个函数中创建新的数据库连接。相反,您应该只创建一个,然后将其作为参数传递给其他函数。
最后,代码背后的逻辑也是错误的。尝试更新不存在的行不是一个错误。更不用说这种情况永远不会发生,因为您的代码应该验证用户ID并禁止除当前用户之外的任何ID。如果您假设该值可能是故意的,那么任何用户都可以更改任何其他用户的密码。