0

我正在尝试为我正在制作的系统编写注册系统。目前,我收到一个 MySQL 错误,每次看到它都让我想把头撕下来。

 function UserRegister($user,$pass,$email,$first,$last)
 {
$sqlfirst = mysql_real_escape_string($first);
$sqllast = mysql_real_escape_string($last);
$sqluser = mysql_real_escape_string($user);
$hashpass = crypt($pass);
$sqlpass = mysql_real_escape_string($hashpass);
$sqlemail = mysql_real_escape_string($email);
$sql = "SELECT * 
 FROM   planerentalusers 
 WHERE  user = '$sqluser' ";
if($result = mysqli_query($GLOBALS['db'],$sql))
{   
    $rowcount=mysqli_num_rows($result);
    if($rowcount == 1)
    {
        echo "ERROR: There is already an account with that username! Click <a href='/PHPCalTest/login.php>here </a>to login if this is you. Otherwise, go back and try a different username.";
    }
    else
    {
        $sql2 = "INSERT INTO planerentalusers (first,last,user,pass,email) VALUES ('$sqlfirst','$sqllast','$sqluser','$sqlpass','$sqlemail')";
        $result2 = mysqli_query($GLOBALS['db'],$sql);
        if($result2 == true)
        {
            return true;
        }
        else return false;
    }
}
else return false;
mysqli_free_result($result);
}

上面是引发错误的函数。没有抛出 PHP 堆栈跟踪,所以这就是我指出的:查询失败。但是怎么做,我不明白。也许有人可以指出我正确的方向。

4

1 回答 1

2

这不是您问题的直接答案。它已经在注释行之间的某个地方解决了。

现在,如果您愿意,您可以简化和保护您的代码:

  1. 使用准备好的语句。这是很自然的,因为您已经在使用mysqli_*扩展程序。您传递给准备好的INSERT语句的参数将被正确转义。
  2. 利用INSERT IGNORE语法并检查受影响的行affected_rows。这样,您只需访问数据库一次即可完成所有您需要做的事情。

为了INSERT IGNORE正常工作,您必须对列进行UNIQUE约束。username

ALTER TABLE planerentalusers ADD UNIQUE (username);

现在,如果您发出一条INSERT IGNORE语句并且用户名不存在,则会插入一行并affected_rows返回1。如果用户名已经存在,则IGNORE子句将允许您的INSERT语句完成而不会引发错误affected_rows并将返回0

话虽如此,您的功能的改进版本可能看起来像

function UserRegister($db, $username, $pass, $email, $first, $last) {
    $sql = "INSERT IGNORE INTO planerentalusers (first, last, username, pass, email) VALUES (?, ?, ?, ?, ?)";
    // prepare the statement
    $stmt = $db->prepare($sql);
    if (!$stmt) {
        die('Can\'t prepare: ' . $db->error); //TODO better error handling
    }
    // bind parameters
    $stmt->bind_param('sssss', $first, $last, $username, $pass, $email);
    if (!$stmt) {
        die('Can\'t bind parameters: ' . $db->error); //TODO better error handling
    }
    // execute
    $stmt->execute();
    if (!$stmt) {
        die('Query execution failed: ' . $db->error); //TODO better error handling
    }
    // get the number of affected rows
    $affected_rows = $stmt->affected_rows;
    // close the statement
    $stmt->close();

    return $affected_rows;
}

和调用代码

$first    = $_POST['first'];   
$last     = $_POST['last'];    
$username = $_POST['username'];
$pass     = crypt($_POST['pass']);
$email    = $_POST['email'];

//create a connection to the database
$db = new mysqli('localhost', 'user', 'password', 'dbname');
if ($db->connect_errno) {
    die('Connection failed: ' . $db->connect_error); //TODO better error handling
}

if (!UserRegister($db, $username, $pass, $email, $first, $last)) {
    echo "ERROR: There is already an account with that username! Click <a href='/PHPCalTest/login.php'>here </a>to login if this is you. Otherwise, go back and try a different username.";
} else {
    echo "Account successfully created";
}

注意

  1. 对打开的数据库连接的引用被显式传递给函数,而不是使用$_GLOBALS['db']
  2. 表示逻辑(回显错误消息和链接)移出到调用代码
  3. 基本的错误处理在整个函数中实现
于 2013-08-09T03:51:48.167 回答