尝试使用准备好的语句更新数据库中的字段

时间:2018-10-31 17:38:57

标签: php mysql database mysqli

我整天都呆在这里,在搜索了许多网站(包括该网站)后,我得出的结论是,由于我的能力不足,我之前没有被问过这个问题。

我在这里有一条准备好的声明,我想根据用户名和电子邮件更新数据库中的密码字段,其更新而不是插入的原因是因为这是我的安全保护,因为它不批准网站摄影师,除非他们已发送链接

<?php
if (isset($_POST['approved-photographer'])) {
    require 'dbh.php';

    $username  = $_POST['username'];
    $email     = $_POST['mail'];
    $password  = $_POST['password'];
    $password2 = $_POST['password-repeat'];

    if (empty($username) || empty($email) || empty($password) || 
        empty($password2)) 
    {
        header("location:signup.php?error=emptyfields&username=" . $username 
    . "&mail=.$email");
        exit();
     } elseif ($password !== $password2) {
        header("location:approvedphoto.php?error=passwordcheck&username=" . 
        $username . "&mail=" . $email);
        exit();
    } else {
        $sql = "SELECT Password 
                FROM photographers 
                WHERE Username= '$username' 
                AND Email= '$email'";

    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)) {
        header("location:approvedphoto.php?error=sqlerror");
        exit();
    } else {
        $sql = "INSERT INTO photographers (Password) VALUES (?)";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
            header("location:approvedphoto.php?error=sqlerror2");
            exit();
        } else {
            $hashedpwd = password_hash($password, PASSWORD_DEFAULT);

            mysqli_stmt_bind_param($stmt, "s", $hashedpwd);
            mysqli_stmt_execute($stmt);
            header("location:signin.php?signup=success");
            exit();
        }
        }
        }
        }

任何帮助将不胜感激。感谢您阅读

1 个答案:

答案 0 :(得分:1)

使用MySQLi的简短答案是您没有绑定参数,可以使用mysqli_stmt_bind_param来完成(未来的读者,由于编辑,最后一条语句现在不相关了)。总体而言,您的sql语句编辑后似乎还不清楚,您通常是在更新密码(在这种情况下,您需要一个WHERE子句,这样就不必更新每个人的密码),或者应该使用密码插入新用户。

这是一个或多或少的切线答案,但是我想为使用PDO(而不是mysqli)而戴上帽子。 MySQLi仅使用一种数据库形式MySQL。另外,它允许对数据库交互的面向对象的解决方案要少得多。这是如何通过PDO完成此操作的示例:

//specifies the driver, ip/database etc. Swap out for your ip and database used
$driverStr = 'mysql:host=<ip>;dbname=<database>;charset=utf8';
//you can set some default behaviors here for your use, I put some examples
//I left a link below so you can see the different options
$options = [
    //spew exceptions on errors, helpful to you if you have php errors enabled
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

//substite what you need for username/password here as well, $options can be omitted
$conn = new PDO($driverStr, '<username>', '<password>', $options);

Link to the aforementioned attributes

现在我们已经建立了联系:

//I used a "named parameter", e.g. :password, instead of an anonymous parameter
$stmt = $conn->prepare("UPDATE Photographers SET password = :password WHERE Username = :username");

//with our prepared statement, there's a few ways of executing it

//1) Using #bind*
//there's also #bindValue for not binding a variable reference
//for params, PARAM_STR is default and can be safely omitted
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->bindParam(':username', $username);
$stmt->execute();

//2) Using execute directly
$stmt->execute(['password' => $password, 'username' => $username]);

然后,该语句是查询,而不仅仅是数据库更新/插入,我们可以简单地检索该语句的结果。通过使用#bindParam,您还可以只更新变量的值并根据需要重新执行该语句,这可能对其他一些语句很有用。

//see #fetch and #fetchAll's documentation for the returned data formatting
$results = $stmt->fetchAll(PDO::FETCH_OBJ); //return it as a php object
$results = $stmt->fetch(PDO::FETCH_NUM)[0]; //unsafely retrieve the first value as a number

多年来,我发现此方法比mysqli_*甚至不推荐使用的mysql_*方法中的任何一种都更加清洁和可管理。