【问题标题】:Unexpected results when passing values from PHP to Ajax using json_encode使用 json_encode 将值从 PHP 传递到 Ajax 时出现意外结果
【发布时间】:2021-02-06 12:35:08
【问题描述】:

目标:为网站开发注册表

问题:PHP 使用 json_encode 函数将意外结果返回给 Ajax(例如,当它应该返回 DUPLICATE_EMAIL 时返回 DUPLICATE_USERNAME)。

代码解释/算法

  1. 用户在注册表中输入他们的详细信息(用户名、电子邮件等)
  2. 单击提交按钮时,输入由 PHP 脚本 (registrationProcess.php) 通过 POST 获取
  3. 运行数据库检查,以便用户名和电子邮件可用(这里我们假设它们不可用)
  4. PHP 通过 Ajax 将值返回给前端。它返回两个字符串,DUPLICATE_USERNAMEDUPLICATE_EMAIL;执行此操作的函数是 handleRegisterError($error_type)
  5. 根据返回的字符串,正确更改网页的 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

标签: php ajax


【解决方案1】:

我已经找到问题的原因了。

单击提交按钮时,所有值实际上都从表单发送到正确的 PHP 脚本。处理了这些值并返回了具有正确错误的正确 JSON 对象。

然后,由于提交按钮功能,页面刷新了。现在,所有表单变量都设置回空,例如username = ""email = "" 等。这些变量再次被同一个脚本使用并针对现有数据库记录进行测试,这反过来又导致错误的第二个错误 ( DUPLICATE_USERNAME 而不是 DUPLICATE_EMAIL)。

我似乎遇到了算法错误,因为我设计的代码流会导致错误。然而,我找到了一个关于创建注册/登录页面的很棒的教程,我已经测试了它的代码(并且它有效!) - follow this link

感谢大家,特别是 Peter Mortensen,感谢大家耐心等待这个错误!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2013-11-07
    • 1970-01-01
    • 2017-10-04
    • 2010-11-09
    • 2020-04-25
    相关资源
    最近更新 更多