簡體   English   中英

從用戶輸入構建動態 PHP 准備語句

[英]Building a dynamic PHP prepared statement from user entry

我有一個包含學生記錄的數據庫,大約有 50 列左右,所有這些都需要可搜索。 我熟悉如何通過附加字段來構建動態搜索查詢。 我似乎找不到任何關於使用本質上是動態的准備好的語句搜索 MySQL 數據庫的示例。 例如,在搜索時您只會輸入您需要搜索的字段,因此,您如何根據用戶輸入構建動態准備語句?

這是一個如何在沒有准備好的語句的情況下執行此操作的示例,但是這很容易發生 SQL 注入。 我需要用一個函數“清理”每個變量。 但是,使用准備好的聲明會更安全。

function clean($con,$var){
    $var = trim($var);
    $var = strtolower($var);
    $var = mysqli_real_escape_string($con,$var);
    return $var;
}

if(isset($_REQUEST['sub'])){

    if(isset($_REQUEST['student_fname'])){
        $student_fname = null;
        if($_REQUEST['student_fname'] != ''){
            $student_fname = '&& `student_fname` = \''.clean($con,$_REQUEST['student_fname']).'\' ';
        }
    }
    if(isset($_REQUEST['student_lname'])){
        $student_lname = null;
        if($_REQUEST['student_lname'] != ''){
            $student_lname = '&& `student_lname` = \''.clean($con,$_REQUEST['student_lname']).'\' ';
        }
    }

    $sql = "SELECT * FROM `student_records` 
    WHERE 1=1 
    $student_fname
    $student_lname
    ORDER BY class ASC, student_lname ASC";
    echo $sql;
}

與許多事情一樣,使用 PDO 會容易得多。 但是,就在我的腦海中,這就是我將如何處理它。 你需要在這里建造3個結構。 SQL、參數類型列表(“s”或“i”)和參數列表本身。 這一切都非常簡單。

如果您以前沒有這樣做過,將它放入bind_param()函數可能會有點棘手,但正如其他地方詳述那樣,一旦您將所有參數都放入數組中, 參數解包運算符就可以很好地工作。

對於 POST 變量,請記住empty()檢查數組元素是否存在,以及它是否為非空。 這將為您節省額外的檢查,唯一的警告是empty("0") === true

<?php
if (isset($_REQUEST['sub'])) {
    $types = "";
    $where = [];
    $params = [];

    if (!empty($_REQUEST['student_fname'])) {
        $types .= 's';
        $where[] = 'student_fname = ?';
        $params[] = $_REQUEST['student_fname'];
    }
    if (!empty($_REQUEST['student_lname'])) {
        $types .= 's';
        $where[] = 'student_lname = ?';
        $params[] = $_REQUEST['student_lname'];
    }

    if (count($where)) {
        $where = "AND " . implode(" AND ", $where);
    } else {
        $where = "";
    }

    $sql = "SELECT * FROM student_records
    WHERE 1=1 
    $where
    ORDER BY class ASC, student_lname ASC";

    $stmt = $con->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    while ($res = $stmt->get_result()) {
        // ....
    }
}

請注意,此代碼允許某人列出整個數據庫; 如果這不是您的意圖, if (count($where))所有內容包裝在if (count($where))語句中。


在 PDO 中,事情要容易得多,不需要綁定並且參數已經作為數組傳遞了。

<?php
if(isset($_REQUEST['sub'])){
    $where = [];
    $params = [];

    if(!empty($_REQUEST['student_fname'])) {
        $where[] = 'student_fname = ?';
        $params[] = $_REQUEST['student_fname'];
    }
    if(!empty($_REQUEST['student_lname'])){
        $where[] = 'student_lname = ?';
        $params[] = $_REQUEST['student_lname'];
    }

    if (count($where)) {
        $where = "AND " . implode(" AND ", $where);
    } else {
        $where = "";
    }

    $sql = "SELECT * FROM student_records
    WHERE 1=1 
    $where
    ORDER BY class ASC, student_lname ASC";

    $stmt = $con->prepare($sql);
    $stmt->execute($params);
    $data = $stmt->fetchAll(\PDO::FETCH_ASSOC);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM