Как я могу динамически построить параметризованный запрос для RedBeanPHP 4?

Итак, у меня есть некоторые данные, поступающие через POST из формы с большим количеством флажков, и я пытаюсь найти записи в базе данных, соответствующие отмеченным параметрам. Есть четыре набора флажков, каждый из которых отправляется в виде массива. Каждый набор флажков представляет один столбец в базе данных, а значения из флажков сохраняются в виде строки с разделителями-запятыми. Значения, которые я ищу, не обязательно будут последовательными, поэтому вместо одного LIKE %value% я думаю, что мне нужно разбить его на серию операторов LIKE, соединенных с помощью AND. Вот что у меня есть:

$query = "";
        $i = 1;
        $vals = [];
        foreach($_POST["category"] as $val){
            $query .= "category LIKE :cat".$i." AND ";
            $vals[":cat".$i] = "%".$val."%";
            $i++;
        }
        $i = 1;
        foreach($_POST["player"] as $val){
            $query .= "player LIKE :plyr".$i." AND ";
            $vals[":plyr".$i] = "%".$val."%";
            $i++;
        }
        $i = 1;
        foreach($_POST["instrument"] as $val){
            $query .= "instrument LIKE :inst".$i." AND ";
            $vals[":inst".$i] = "%".$val."%";
            $i++;
        }
        $i = 1;
        foreach($_POST["material"] as $val){
            $query .= "material LIKE :mat".$i." AND ";
            $vals[":mat".$i] = "%".$val."%";
            $i++;
        }
        $query = rtrim($query, " AND ");

        $tubas = R::convertToBeans("tuba", R::getAll("SELECT * FROM tuba WHERE ".$query, $vals));

Кажется, это работает в моем предварительном тестировании, но лучший ли это способ сделать это? Будет ли это безопасно от SQL-инъекций? Спасибо!


person dev_willis    schedule 27.02.2015    source источник


Ответы (1)


Пока вы используете параметризованные запросы (как и вы), вы должны быть защищены от SQL-инъекций. Однако есть крайние случаи, когда использование UTF-7 PDO уязвимо (я думаю, что redbean основан на PDO)

Я бы изменил код на что-то вроде этого, чтобы свести к минимуму беспорядок foreach.

$query = 'SELECT * FROM tuba';
$where = [];
$params = [];

$checkboxes = [
    'category',
    'player',
    'instrument',
    'material'
];

foreach ($checkboxes as $checkbox) {
    if (!isset($_POST[$checkbox])) {
        // no checkboxes of this type submitted, move on
        continue;
    }
    foreach ($_POST[$checkbox] as $val) {
        $where[] = $checkbox . ' LIKE ?';
        $params[] = '%' . $val . '%';
    }
}

$query .= ' WHERE ' . implode($where, ' AND ');

$tubas = R::convertToBeans('tuba', R::getAll($query, $params));
person JimL    schedule 27.02.2015
comment
RedBean использует PDO. Я посмотрю на UTF-7 PDO. Спасибо, что подкинули мне немного знаний! Это намного чище. - person dev_willis; 28.02.2015
comment
@Dave np, рад помочь. Не так давно протестировал redbean, интересно :) - person JimL; 28.02.2015
comment
Я копаю это. Отлично подходит для быстрого развития. - person dev_willis; 28.02.2015