php mysqli bind_param $ insert-> execute()始终返回true

时间:2017-10-08 07:04:26

标签: php mysql mysqli

我有一个模型方法,在执行时总是返回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。

发生了什么事?

2 个答案:

答案 0 :(得分:1)

这是正常行为。如果execute()返回true,则这意味着执行语句时没有SQL代码/数据库/网络错误。如果没有记录受到语句的影响,将其视为错误是很自然的。

正如@SearchAndResQ建议的那样,您可以检查受影响的行。但请注意,这有其注意事项,因此您应首先阅读MySQL的ROW_COUNT() documentationmysql_affected_rows() documentation(其中一个必须由PHP在幕后使用)。

值得注意的是,UPDATE的行为取决于建立与数据库的连接时设置的标志,并且REPLACEON DUPLICATE KEY UPDATE可能会出现意外行为。

就个人而言,在这种情况下我更喜欢另一种方法。我首先SELECT有问题的记录FOR UPDATE,然后查看结果集以检查是否有任何记录受到影响。然后我在记录仍然被锁定时进行更新。你需要使用交易(我正在做的事情,所以额外的努力也不算太糟糕)。

恕我直言,该方法更具可移植性,其结果更易理解,因此通常比affected_rows机制更安全。它的缺点是你需要使用事务并且它可能更慢。

答案 1 :(得分:0)

坦率地说,你的基本前提是错误的。事实上,

你不应该关心execute()是否返回false

只有在出现严重的数据库错误时才会发生这种情况。但是在这种情况下,在发生错误的特定操作的详细信息中没有意义。如果出现严重的数据库错误,则只显示通用的服务器错误页面。

另一方面,作为程序员,您必须才能知道,在更新过程中发生了什么特定错误,以便能够修复它。而且您的代码无助于您。

我写了一篇文章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。如果您假设该值可能是故意的,那么任何用户都可以更改任何其他用户的密码。