Построение динамического PHP подготовленного оператора из пользовательского ввода - PullRequest
1 голос
/ 14 мая 2019

У меня есть база данных с записями студентов, около 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;
}

1 Ответ

3 голосов
/ 14 мая 2019

Как и во многих других случаях, это было бы намного проще с 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 " . explode(" 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)).


В 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 " . explode(" 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...