【发布时间】:2021-02-06 12:35:08
【问题描述】:
目标:为网站开发注册表
问题:PHP 使用 json_encode 函数将意外结果返回给 Ajax(例如,当它应该返回 DUPLICATE_EMAIL 时返回 DUPLICATE_USERNAME)。
代码解释/算法:
- 用户在注册表中输入他们的详细信息(用户名、电子邮件等)
- 单击提交按钮时,输入由 PHP 脚本 (
registrationProcess.php) 通过 POST 获取 - 运行数据库检查,以便用户名和电子邮件可用(这里我们假设它们不可用)
- PHP 通过 Ajax 将值返回给前端。它返回两个字符串,
DUPLICATE_USERNAME或DUPLICATE_EMAIL;执行此操作的函数是handleRegisterError($error_type) - 根据返回的字符串,正确更改网页的 UI
此函数是在单击提交按钮后调用的脚本的一部分。
<?php
/**
* This function gets called in the PHP script if a registration error has been found. It is passed either DUPLICATE_USERNAME or DUPLICATE_EMAIL.
*/
function handleRegisterError($error_type) {
switch($error_type) {
case "DUPLICATE_USERNAME":
$data = array("error" => "DUPLICATE_USERNAME");
echo json_encode($data);
break;
case "DUPLICATE_EMAIL":
$data = array("error" => "DUPLICATE_EMAIL");
echo json_encode($data);
break;
default:
echo "Unexpected error in registrationProcess.php"
break;
}
}
/>
现在,前端 HTML 注册页面上接收代码的 JavaScript 代码:
<script>
$.ajax({
dataType: 'json',
url: "../php/registrationProcess.php",
success: function(data) {
console.log("SUCCESS: " + data.error);
handleError(data.error);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("ERROR CALLING AJAX! textStatus = " + textStatus + " | errorThrown = " + errorThrown);
}
});
function handleError(errorType) {
console.log("errorType = " + errorType);
switch(errorType) {
case "DUPLICATE_USERNAME":
// Display duplicate username error
$("#username-error").attr("hidden", false);
$("#username-input-field").css("margin-bottom", 8);
break;
case "DUPLICATE_EMAIL":
// Display duplicate email error
$("#email-error").attr("hidden", false);
$("#email-input-field").css("margin-bottom", 8);
break;
}
}
</script>
接收代码包含从 PHP 接收结果的基本 Ajax 表单。它将接收到的变量 (data.error) 传递给 handleError 函数,该函数又包含一个 switch 语句,该语句会针对重复的用户名/电子邮件错误更改 UI。
调试:
当 PHP 从 json_encode 发送值时,它会回显它正在传输到网站的 JSON 代码,因此我可以很容易地看到 PHP 作为 JSON 传输的内容。对于JavaScript调试,我使用console.log函数打印"SUCCESS",然后是data.error(应该和PHP传过来的值差不多)。然后,为了安全起见,JavaScript 中使用的错误会从 handleError 函数重复打印到控制台。
您可以看到我用来分析这两个图像中错误的两个调试源的示例,其中从 PHP 传输的 JSON 显示在图像的左上角,控制台显示在图像的右侧:
问题分析
我已将以下用户放入数据库:
- 用户名:Mike
- 电子邮件:mikey@gmail.com
为了测试代码,我运行了两个单独的测试:在第一个测试中,我尝试创建另一个名为 Mike and a different email 的用户名(其中预计会返回DUPLICATE_USERNAME 错误)。在第二次测试中,我尝试使用name Jenna and the email mikey@gmail.com 创建另一个用户名,这预计会导致DUPLICATE_EMAIL 错误。
当用户名重复时,我的代码成功处理了第一种情况:
但是,在第二种情况下,PHP 正确识别了 DUPLICATE_EMAIL 错误,但 JavaScript / Ajax 在发送时以某种方式将其解释为 DUPLICATE_USERNAME。
我在我的代码中做错了什么导致了这个错误?是否可能是从以前的数据传输中保存的网页上的某些状态?
感谢您花时间处理这个问题!
registrationProcess.php 的脚本:
<?php
include 'secureFunctions.php';
$username = "";
$birthday = "";
$gender = "";
$email = "";
$password = "";
$username = getVariable('username');
$birthday = getVariable('birthday');
$gender = getVariable('gender');
$email = getVariable('email');
$password = getVariable('password');
$db_host = "sql7.freesqldatabase.com";
$db_username = "sql7369409";
$db_password = "*******";
$db_name = "sql7369409";
$conn = new mysqli($db_host, $db_username, $db_password, $db_name);
if(mysqli_connect_error()) {
die("Database connection failed: " . mysqli_connect_error);
}
if($gender != "") {
// Edit gender for the database
switch ("gender") {
case "male":
$gender = "m";
break;
case "female":
$gender = "f";
break;
case "other":
$gender = "o";
break;
}
}
if($birthday != "") {
// Edit birthday for the database
$arr = explode('/', $birthday);
$birthday = $arr[2] . '-' . $arr[1] . '-' . $arr[0];
}
$sql = "INSERT INTO users (id, username, birthday, gender, email, password)
VALUES (NULL, '$username', '$birthday', '$gender', '$email', '$password')";
if (mysqli_query($conn, $sql)) {
echo "New record created successfully!";
header("Location: ../pages/index.html");
exit();
}
else {
handleRegisterError(registrationGetErrorType(mysqli_error($conn)), "TRUE");
}
function handleRegisterError($error_type, $devValue) {
//echo "errorType = $error_type ";
if($devValue == "TRUE") {
/*
switch ($error_type) {
case "DUPLICATE_USERNAME":
//echo "test2";
$data = array("error" => "DUPLICATE_USERNAME");
echo json_encode($data);
break;
case "DUPLICATE_EMAIL":
//echo "test1";
$data = array("error" => "DUPLICATE_EMAIL");
echo json_encode($data);
break;
case "UNKNOWN":
$data = array("error" => "UNKNOWN");
echo json_encode($data);
break;
}
*/
//$data;
if($error_type == "DUPLICATE_USERNAME") {
//echo " t1 ";
$data = array("error" => "DUPLICATE_USERNAME");
//echo json_encode($data);
} elseif($error_type == "DUPLICATE_EMAIL") {
//echo " t2 ";
$data = array("error" => "DUPLICATE_EMAIL");
//echo json_encode($data);
} else {
$data = array("error" => "UNKNOWN");
//echo json_encode($data);
}
echo json_encode($data);
}
}
?>
上面的脚本也用到了secureFunctions.php的一些方法:
<?php
/**
* Retrieves a variable from HTML using the null coalesce operator (for security reasons)
* @param mixed $variableName
* @return void
*/
function getVariable($variableName) {
$result = $_POST[$variableName] ?? '';
return $result;
}
/**
* There are two types of registration errors: (1) username already in use (2) email already in use or (3) Unknown error
* First two errors look like this:
* (1): Duplicate entry 'skorjanc.survey@gmail.com' for key 'email'
* (2): Duplicate entry 'King_Fish' for key 'name'
*
* @param mixed $sqlDbText The error text from the server
* @return (1) DUPLICATE_USERNAME (2) DUPLICATE_EMAIL (3) UNKNOWN
*/
function registrationGetErrorType($sqlDbText) {
$filtered = str_replace("'", "", $sqlDbText); // Replace single quotes with air
$array = explode(" ", $filtered);
$key = $array[count($array)-1];
if($key == "email") {
return "DUPLICATE_EMAIL";
} elseif($key == "name") {
return "DUPLICATE_USERNAME";
}
return "UNKNOWN";
}
?>
作为ArJay suggested,我还在registrationGetErrorType 方法中为这两种情况(重复的用户名和重复的密码)附加了$array 和$key 的值:
(1) 重复用户名
array = Array ( [0] => Duplicate [1] => entry [2] => King_Fish [3] => for [4] => key [5] => name )
key = name
(2) 重复电子邮件
array = Array ( [0] => Duplicate [1] => entry [2] => skor@gmail.com [3] => for [4] => key [5] => email )
key = email
【问题讨论】:
-
您尝试过什么检查此错误的开始位置?通常,这要么是 Javascript 问题(例如浏览器中的某些内容处理不正确,例如请求已经发送了不正确的值),要么是 PHP 问题(所有值都正确发送,但未正确处理)
-
我认为这个错误始于 Javascript,在接收 json 的 ajax 函数部分。因为正如在第三张图片中可见的那样,PHP 发送了一个带有“DUPLICATE_EMAIL”的正确 json,然后 javascript 不知何故将其解释为 DUPLICATE_USERNAME
-
请为
registrationProcess.php添加脚本。这将使帮助变得容易得多。 -
在编辑@ArJay 中包含了相关脚本
-
问题结尾处来自 rget 函数的键和数组的值-@ArJay