问题描述
目标:为网站开发注册表格
问题:PHP使用json_encode函数将意外结果返回给Ajax(例如,它应返回DUPLICATE_USERNAME
时返回DUPLICATE_EMAIL
)。
代码说明/算法:
- 用户在注册表格中输入其详细信息(用户名,电子邮件等)
- 单击提交按钮后,PHP脚本(
registrationProcess.PHP
)通过POST获取输入 - 运行数据库检查,以便提供用户名和电子邮件(此处我们假设它们不可用)
- PHP通过Ajax将值返回到前端。它返回两个字符串,
DUPLICATE_USERNAME
或DUPLICATE_EMAIL
;执行此操作的功能是handleRegisterError($error_type)
- 根据返回的字符串,正确更改网页的用户界面
<?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>
接收代码由基本的Ajax表单组成,用于从PHP接收结果。它将接收到的变量(data.error
)传递到handleError
函数,该函数又包含一个switch语句,该语句更改UI来解决重复的用户名/电子邮件错误。
调试:
当PHP从json_encode发送值时,它回显正在传输到网站的JSON代码,因此我可以轻松地看到PHP作为JSON传输的内容。对于JavaScript调试,我使用console.log函数打印"SUCCESS"
,然后打印data.error
(应该类似于PHP传输的值)。为了安全起见,然后从handleError
函数将JavaScript中使用的错误反复打印到控制台。
您可以看到我用来分析这两个图像中的错误的两种调试源的示例,其中从PHP传输的JSON在图像的左上方,控制台在图像的右侧。 :
问题分析
为了测试代码,然后运行了两个单独的测试:在 第一个测试 中,我尝试创建另一个名为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一样,在两种情况下(用户名重复和密码重复),我还在$array
方法中附加了$key
和registrationGetErrorType
的值:
(1)DUPLICATE_USERNAME
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
解决方法
我已经找到了问题的原因。
单击“提交”按钮时,所有值实际上都已从表单发送到正确的PHP脚本。处理了这些值,并返回了具有正确错误的正确JSON对象。
但是,由于提交按钮功能,页面刷新了。现在,所有表单变量都被重新设置为空,例如username = ""
,email = ""
等。这些变量再次被同一脚本使用并针对现有数据库记录进行了测试,从而导致错误的第二个错误(DUPLICATE_USERNAME而不是DUPLICATE_EMAIL)。
似乎我遇到了算法错误,因为我以导致错误的方式设计了代码流。但是,我找到了关于创建注册/登录页面的很棒的教程,我已经对其代码进行了测试(并且可以运行!)-follow this link。
感谢大家,特别是彼得·莫滕森(Peter Mortensen)对这个错误的耐心!