如何从 Prepared 语句中获取行数据,然后将其与 AJAX() 函数一起使用

Posted

技术标签:

【中文标题】如何从 Prepared 语句中获取行数据,然后将其与 AJAX() 函数一起使用【英文标题】:How do I get the row data from a Prepared statement and then use it with AJAX() function 【发布时间】:2017-11-05 16:10:10 【问题描述】:

使用 mysqli,我的代码运行良好,但是当我尝试使用准备好的语句时,为了提高安全性,我无法将值返回给我的 AJAX() 函数。

这是我的 js 代码

function validateCoSigner()
var contractNo = $('#cosigner_reference_number').val();
var firstName = $('#cosigner_firstname').val();
var lastName = $('#cosigner_lastname').val();
$.ajax(
    type: 'POST',
    url: 'php/retrieve-applicant1-details.php',
    // dataType: 'json',
    data: 
        'contractNo': contractNo,
        'firstName' : firstName,
        'lastName'  : lastName
    , 
    success: function(json) 
        showCoSigner();
        console.log(json);
        $('#contractID').val(json.contractID);
        $('#loanpurpose').val(json.loanpurpose);
        $('#applicant1_firstname').val(json.applicant1_firstname);
        $('#applicant1_middlename').val(json.applicant1_middlename);        
        $('#applicant1_surname').val(json.applicant1_surname);
        $('#applicant1_dateofbirth').val(json.applicant1_dateofbirth);
    , 
    error: function() 
        alert ('error2');

    
);

这是使用 mysqli 函数的retrieve-applicant1-details.php 文件:

<?php
header('Content-Type: application/json');
$conn = mysqli_connect("localhost", "root","","xxx");

$contractno = $_POST['contractNo'];
$firstname = $_POST['firstName'];
$lastname = $_POST['lastName'];

$sql = "SELECT * FROM contract WHERE contractID='$contractno' AND applicant1_firstname='$firstname' AND applicant1_surname='$lastname'";
$query = mysqli_query($conn,$sql);
$num_row = mysqli_num_rows($query);
$row=mysqli_fetch_assoc($query);
if( $num_row == 1 ) 
    $obj = [
        'contractID'                =>($row['contractID']), 
        'loanpurpose'               =>($row['loanpurpose']), 
        'applicant1_firstname'      =>($row['applicant1_firstname']), 
        'applicant1_middlename'     =>($row['applicant1_middlename']), 
        'applicant1_surname'        =>($row['applicant1_surname']), 
        'applicant1_dateofbirth'    =>($row['applicant1_dateofbirth']), 
    ];
    
else 
    echo 'The reference number, firstname and lastname does not match';
    exit;


echo json_encode($obj);
?>

如果我使用如下准备好的语句,我无法弄清楚如何正确获取数据,以便我可以将值返回给我的 Ajax 函数,以便它可以显示在我的表单中。

<?php
header('Content-Type: application/json');
$conn = mysqli_connect("localhost", "root","","xxx");

$contractno = $_POST['contractNo'];  //not sure if I still need to use mysqli_real_escape_string here.
$firstname = $_POST['firstName'];
$lastname = $_POST['lastName'];

// prepare statement        
$stmt = $conn->prepare("SELECT * FROM contract WHERE contractID=? AND applicant1_firstname=? AND applicant1_surname=?");
// bind
$stmt->bind_param("iss", $contractno, $firstname, $lastname);
// execute
$stmt->execute();
if ($stmt->errno) 
    echo "FAILURE!!! " . $stmt->error;

else echo "Updated $stmt->affected_rows rows";

$row = $stmt->fetchObject();
$obj = (
    'contractID'                =>($row['contractID']), 
    'loanpurpose'               =>($row['loanpurpose']), 
    'applicant1_firstname'      =>($row['applicant1_firstname']), 
    'applicant1_middlename'     =>($row['applicant1_middlename']), 
    'applicant1_surname'        =>($row['applicant1_surname']), 
    'applicant1_dateofbirth'    =>($row['applicant1_dateofbirth']), 
);

echo json_encode($obj);
?>

我是新手。任何建议将不胜感激。

【问题讨论】:

一方面,fetchObject() 是一种 PDO 方法,而您正在使用 mysqli_。 【参考方案1】:

在 MySQLi 中准备语句时,您需要使用 bind_result() 将结果列绑定到变量中,如果您不准备语句,您将使用该变量而不是 $row 数组 (就像你使用 mysqli_fetch_*() 函数一样)。

您绑定的变量数量与所选列的数量相匹配,这一点很重要。这就是我修改您的查询以匹配它的原因。

然后你需要fetch()结果。实施这些更改后,您的查询应如下所示

$stmt = $conn->prepare("SELECT contractID, 
                               loanpurpose, 
                               applicant1_firstname, 
                               applicant1_middlename, 
                               applicant1_surname, 
                               applicant1_dateofbirth 
                        FROM contract 
                        WHERE contractID=? 
                          AND applicant1_firstname=? 
                          AND applicant1_surname=?");
$stmt->bind_param("iss", $contractno, $firstname, $lastname);
$stmt->execute();
$stmt->bind_result($contractID, $loanpurpose, $applicant1_firstname, $applicant1_middlename, $applicant1_surname, $applicant1_dateofbirth);
if ($stmt->errno) 
    die("Query failed to execute: " . $stmt->error);

if ($stmt->fetch()) 
    echo json_encode(array("contractID" => $contractID, 
                           "loanpurpose" => $loanpurpose,  
                           "applicant1_firstname" => $applicant1_firstname,  
                           "applicant1_middlename" => $applicant1_middlename,  
                           "applicant1_surname" => $applicant1_surname,  
                           "applicant1_dateofbirth" => $applicant1_dateofbirth));
 else 
    echo "No matching rows returned.";

$stmt->close();

不,您不应该在使用准备好的语句时使用mysqli_real_escape_string() - 通过转义不需要转义的引号 (IF I use mysqli prepared statements do i need to escape) 会破坏数据。

您可以检查 $stmt-&gt;fetch() 是否返回 true,而不是使用 $stmt-&gt;num_rows == 1 - 因为您只期望一行,所以您不需要检查数量 - 只是 something 被提取。根据手册,$stmt-&gt;fetch() 返回 true 表示成功查询,null 如果没有返回行。 这种方法可能更好的原因是,您可以避免在使用$stmt-&gt;num_rows; 之前调用$stmt-&gt;store_result();。这在资源方面更有效,但也节省了一些打字;-)

还请注意,echo "Updated $stmt-&gt;affected_rows rows"; 在这里使用没有意义,因为您正在运行 SELECT 查询,而不是 UPDATE 查询。如果要查看返回的行数,可以改用$stmt-&gt;num_rows;

http://php.net/mysqli-stmt.bind-result http://php.net/mysqli-stmt.fetch http://php.net/mysqli-stmt.num-rows

【讨论】:

非常感谢奇瑞尔。不幸的是,这些值仍然没有到达 AJAX() 函数。我是否也需要在我的 js 文件中进行更改? 啊,我明白了。不,Ajax 本来就很好 - 但返回的 json 应该按名称而不是数字来索引 - 因为您使用 json.contractID 来访问结果。我会更新答案。 成功了,谢谢!! @Qirel 对于我的学习:如果返回的 json 是按数字索引的,我将如何编写 Ajax 来访问结果? 您可以将其作为数组元素访问,即使它们是使用命名或编号索引定义的。对你来说,因为 AJAX 的结果在 json 变量中,所以它应该是 json[0] 感谢您的明确答复!在我的原始 php 文件中,您可能会注意到如果字段不匹配,我会向用户发送一条消息。现在,我尝试使用: if ($stmt->num_rows == 1) 语句,但是当我尝试向用户回显某些内容时似乎总是出错。我认为这是因为我在 AJAX 上苦苦挣扎。抱歉,不知道在你解决了主要问题后我是否可以问更多问题。

以上是关于如何从 Prepared 语句中获取行数据,然后将其与 AJAX() 函数一起使用的主要内容,如果未能解决你的问题,请参考以下文章

我如何打破 foreach 语句,回显其他内容然后继续

MySQL Prepared PDO 语句正在删除反斜杠

检查db prepared语句中是否已存在用户名

使用 Prepared Statement,我如何返回插入行的 id?

启用 SQL 触发器时,Java 中的 Prepared Statement 失败

如何从 MS ACCESS 数据库中的特定行和列中获取值?