要更新帐户,客户必须通过电子邮件链接进行验证。 单击后,SQL 中的值将从 0 设置为 1,并返回成功消息。
如果状态已经是1,应该有一条消息表明帐户已经更新。在我的脚本中,即使状态为零,客户也会收到成功更新的消息,并且不会更新到状态 1。
if (!isset($_GET['token'])){
echo "Link is missing";
}else{
$token = $_GET['token'];
// CHECK IF COLUMN 'verified' HAS VALUE '1'
$stmt = $conn->prepare("SELECT COUNT(*) FROM database WHERE token = ? AND verified = ?");
$status = 1;
$stmt->bind_param("ss", $status, $token);
$res1 = $stmt->execute();
if ($res1 > 0){
echo "Your account is already updated";
}else{
// UPDATE COLUMN 'verified' TO VALUE '1'
$stmt = $conn->prepare("UPDATE database SET verified = ? WHERE token = ?");
$status = 1;
$stmt->bind_param("ss", $status, $token);
$res2 = $stmt->execute();
if ($res2){
echo "Account updated successfully";
}
}
}
您可以使用一个查询和原子操作来完成!
$token = $_GET['token']?? '';
if ($token){
$stmt = $conn->prepare("UPDATE database SET verified = 1 WHERE token = ? AND verified = 0");
$stmt->bind_param("s", $token);
$stmt->execute();
if ($stmt->affected_rows){
echo "Account updated successfully";
}else{
echo "Your account is already updated Or your token is wrong!";
}
} else
echo "Link is missing";
$stmt->affected_rows
将为空!注意: 您可以使用
$stmt->execute([$token])
代替绑定参数并在 PHP 8.1 中执行
mysqli_stmt::execute
成功时返回 true,失败时返回 false。你要检查的是返回值是否大于0,所以你应该获取结果:
$stmt->bind_result($count);
$stmt->fetch();
if ($count > 0)
....
正如 Rob 在评论中提到的,参数是向后的,正如 Alijvhr 所回答的,您可以在单个查询中完成您想要做的事情。另外,行
$res1 = $stmt->execute();
the value of $res1
只告诉你该语句执行是否没有错误,与结果集的内容无关。在 PHP>=8.1 中,默认情况下 mysqli 将引发错误异常,但在此之前,您需要显式检查每个 query()
/prepare()
/execute()
调用,或者调用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
来设置 mysqli 驱动程序生成错误异常。一旦你让 mysqli 进入异常模式,你就可以取消所有 $res1
/$res2
/等检查。
但是,假设在这种情况下,您不能在一个查询中完成所有操作,则应该将这些语句包含在事务中,以防止查询之间的其他进程更改行。例如:用户不小心双击了提交。
这看起来像:
if (!isset($_GET['token'])){
echo "Link is missing";
}else{
$token = $_GET['token'];
try {
$conn->begin_transaction();
// CHECK IF COLUMN 'verified' HAS VALUE '1', and acquire row lock for update
$stmt = $conn->prepare("SELECT FOR UPDATE COUNT(*) FROM database WHERE token = ? AND verified = ?");
$status = 0; // get un-verified rows for lock
$stmt->bind_param("ss", $token, $status); // fixed param order
$res1 = $stmt->execute();
if ($res1 && $stmt->affected_rows < 1) { // fix condition check
echo "Your account is already updated, or an invalid token was provided.";
}else{
// UPDATE COLUMN 'verified' TO VALUE '1'
$stmt = $conn->prepare("UPDATE database SET verified = ? WHERE token = ?");
$status = 1;
$stmt->bind_param("ss", $status, $token);
$res2 = $stmt->execute();
if ($res2 && $stmt->affected_rows == 1){
echo "Account updated successfully";
} else {
// either the query caused an error, or updated some number of rows other than 1.
// mysqli should generate its own exception on error by default in PHP>=8.1, raise one of our own just in case.
$msg = "Unspecified query error has occurred.";
echo $msg;
throw new Exception($msg);
}
}
$conn->commit(); // commit changes
} catch(mysqli_sql_exception|Exception $e) {
$conn->rollback(); // roll back changes
throw $e; // re-throw exception for handling elsewhere
}
}
By default Mysql operates in "implicit transaction" mode where every statement is wrapped in a transaction, so you don't have to worry about collisions and whatnot, but wrapping more complex sets of statements in a single transaction is an important tool to have in your box.