使用带有绑定

时间:2017-12-13 23:17:37

标签: php mysql mysqli

以下代码有效,但我担心SQL注入。

我正在尝试将参数$S传递给某些PHP代码以显示测试结果。工作代码如下:

<?php
    $S = $_GET['S'];
    // $sql = "SELECT `date`, `test` FROM `results` WHERE `id` = \"003-26\"";
    $servername = "localhost";
    $username = "slowLearner";
    $password = "myPassword";
    $dbname = "myDataBase";

    // Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);

    // Check if id exists 
    if(!($stmt = $conn->prepare("SELECT `date`, `test` FROM `results` WHERE `id` = ?"))){
        die("Prepare1 failed: (" . $conn->errno . ") " . $conn->error);
    }

    if(!$stmt->bind_param('s', $S)){
        die("Binding1 parameters failed: (" . $stmt->errno . ") " . $stmt->error);
    }

    $sql = "SELECT `date`, `test` FROM `results` WHERE `id` = '".$S."'";
    // But I believe the line above is prone to SQL injection so 
    // IDEALLY I would prefer to use something like:
    // $result = $conn->query($stmt);
    // but that simply does not work... (zero results is displayed)
    $result = $conn->query($sql);

    if ($result->num_rows > 0) {
        // output data of each row
        while($row = $result->fetch_assoc()) {
                echo "Test Date: " . $row["date"]. ",  Test score: " . $row["test"]. " (s)" . "<br>";
        }
    } else {
        echo "zero results";
    }
    $conn->close();
?>

我在代码中的评论显示我正在尝试(并且失败)使用带有绑定的预准备语句...我正在圈子里用这个,任何帮助都非常感激。< / p>

澄清:

没有这样的错误 - 当我尝试使用绑定时,我根本没有得到任何结果,并且else if ($result->num_rows > 0) {部分显示消息零结果

我确信拥有$sql$stmt是不正确的,因为最终编写$sql的方式使其容易注入...我想要的是什么show是我在绑定方面取得了多大的进展,并且此时我陷入了困境。

修改后的代码:

基于this example我修改了代码(见下文)。但是输出仍然显示zero results,即使我知道有4行与查询匹配:$result = $conn->query($sql);。修改后的代码如下:

if(!$stmt->bind_param('s', $S)){
    die("Binding1 parameters failed: (" . $stmt->errno . ") " . $stmt->error);
}

    $stmt->execute();
    $stmt->bind_result($result);
    $stmt->fetch();

if ($result->num_rows > 0) {

TIA -SL

1 个答案:

答案 0 :(得分:2)

简短回答...请勿使用query,请使用execute

preparebind

之后
if(!$stmt->bind_param('s', $S)){
   die("Binding1 parameters failed: (" . $stmt->errno . ") " . $stmt->error);
}

使用execute并检查返回(如果返回为FALSE则发生错误。如果成功,SELECT应该返回结果集)

// http://php.net/manual/en/mysqli-stmt.execute.php
if(!$stmt->execute()) {
   die("execute failed: (" . $stmt->errno . ") " . $stmt->error);
}

如果我们不使用mysqlnd(本机驱动程序),那么我们就不能使用get_result来返回结果集。

可选地,我们可以执行store_result,认识到大型结果集将需要大量内存。如果我们不这样做,我们仍然可以获取行。 (它的性能/内存权衡。)

// http://php.net/manual/en/mysqli-stmt.store-result.php
$stmt->store_result();

我们可以将行提取到绑定结果变量

// http://php.net/manual/en/mysqli-stmt.bind-result.php
$stmt->bind_result($r_date, $r_test);

fetch函数获取一行并填充我们的绑定结果变量。请注意,这些是对标量变量的引用; fetch不会返回query之类的“结果集”对象。

$cnt = 0;
while($stmt->fetch()) {
   echo "Test Date: " . $r_date . ",  Test score: " . $r_test . " (s)" . "<br>";
   $cnt++;
}
if($cnt === 0) {
   echo "zero results";
}

如果我们做了store_result,我们应该释放内存

$stmt->free_result();    

我们并不总是需要做一个close的陈述,而是它的规范模式;这就处理了我们确实需要这样做的情况。

// http://php.net/manual/en/mysqli-stmt.close.php
$stmt->close();

如果我们使用mysqlnd(本机驱动程序),那么我们可以使用mysqli_stmt_get_result返回结果集,就像我们使用query一样。

是否使用get_result取决于您的代码需要多么便携;如果你的代码需要mysqlnd。

就个人而言,我使用PDO而不是mysqli。