我决定尝试构建一个简单的登录和注册表单,但我遇到了一个问题。
当某人注册时,我明显要求他们填写Name
,E-Mail
,Password
和Confirm Password
。
我正在使用以下代码检查电子邮件是否已在数据库中:
$query = $conn->prepare("SELECT email FROM users WHERE email ='" . $_POST['email'] . "'");
$query->execute();
if ( $query->rowCount() > 0 ) {
$error = true;
$email_again = "E-Mail already exists";
}
我的问题:
当有人输入已经在数据库中的电子邮件时,页面刷新并向他们显示错误。
现在数据库没有将它添加到表中,但是它做的是将id增加1,所以下次当有人用有效的电子邮件签名而不是他们的id为2时它是3,因为有人试图使用已经存在的电子邮件注册
$query = $conn->prepare("SELECT email FROM users WHERE email ='" . $_POST['email'] . "'");
$query->execute();
if ( $query->rowCount() > 0 ) {
$error = true;
$email_again = "E-Mail already exists";
exit();
}
所以我继续将exit();
添加到if
语句中,但如果电子邮件已经在数据库中,它只会在提交后显示空白页。
我该如何解决这个问题?
更新:
Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'me@stephenhinett.co.uk' for key 'email' in /Applications/MAMP/htdocs/tasks/register.php:69 Stack trace: #0 /Applications/MAMP/htdocs/tasks/register.php(69): PDO->exec('INSERT INTO use...') #1 {main} thrown in /Applications/MAMP/htdocs/tasks/register.php on line 69
第69行:
$sql_insert = "INSERT INTO users(name, email, password)
VALUES ('" . $name . "', '" . $email . "', '" . md5($password) . "')";
$conn->exec($sql_insert);
答案 0 :(得分:2)
问题1
if ( $query->rowCount() > 0 ) { $error = true; $email_again = "E-Mail already exists"; exit(); }
所以我继续前进并添加了exit(); if语句但如果电子邮件已经在数据库中,它只会在提交后显示一个空白页面。
您的问题是,当您添加exit
时,您没有添加header
来告诉浏览器输出的内容(如果有的话)。没有输出的exit
将始终是一个暗淡的白色屏幕。 Exit
在那时停止了脚本,因此通常不是非常用户友好的,孤立的。
因此,在退出之前添加标题,以便您的页面可以正确地重定向用户。我还添加了一个$_SESSION
变量,其中包含您要反馈给用户的消息(关于电子邮件重复):
session_start(); //if not already started at the top of the page
if ( $query->rowCount() > 0 ) {
$error = true;
$_SESSION['message'] = "E-Mail already exists.";
header("Location: somepage.php"); //will display session message
exit();
}
在您转到的页面上,设置一个系统来检查消息的sessio值并将消息输出到浏览器窗口。
问题2
阅读您的问题错误:您正尝试在数据库表中复制unqiue密钥(email
)索引,某些脚本函数仍在(尝试)INSERT
复制的电子邮件。 / p>
你还没有向我们展示这个脚本函数(在register.php第69行),所以我不能详细说明这个细节,但你可能有兴趣用On Dupliate Key Update语法来帮助你克服了这一点。
旁注:
如果您已经为SQL使用面向对象的表示法,为什么不使用Prepared Statements?这样更安全,以及检查数据库表中是否已存在电子邮件的更有效方法。
我不明白为什么要在尝试复制电子邮件时增加行ID,为什么要增加id
字段?如果id值是您的主键(PK)并且是MySQL auto_increment
,那么 手动 增量这是非常糟糕的做法并会引起各种相关问题。最好还有另一个表格列,例如repetation_attempts
,这是一个标准tinyint(3)
(或smallint(6)
,无论如何)列(默认为零),然后会更新该列以跟踪重复尝试的次数。试过任何给定的电子邮件行。
答案 1 :(得分:0)
出于安全考虑,我建议您使用准备好的语句。 我不是MySQL专家,但我认为情况就是这样......
出于并发原因,自动增量索引也会在失败的insert语句中递增:
- 查询A执行INSERT语句,数据库保留索引
- 查询B执行INSERT语句,DB保留索引
- 查询A失败但“B”完成了他的陈述并且它是并发的
- 为了保证一致性,A的指数将被简单地浪费
醇>
正如您所说,您可以手动检查电子邮件是否已存在。 伪代码:
if(mail_already_exists()){ show_error(); }else{ insert_data(); }
答案 2 :(得分:0)
数据库不会将其添加到表中,但它的作用是什么 将id增加1,以便下次有人注册时有效 电子邮件,而不是他们的身份2是3,因为有人试图 使用已经存在的电子邮件注册
除非您实际插入数据,否则我认为没有理由为什么ID会增加。使用函数进行重复记录检查。