Страницы

Поиск по вопросам

среда, 4 марта 2020 г.

Как грамотно вставить название таблицы из переменной в SQL-запрос? PHP/PDO

#php #mysql #sql #pdo


Забиндить невозможно, а аналогов mysql_real_escape_string() у PDO нет. Будет ли правильно
использовать PDO::quote() ?

"SELECT * FROM" . $pdo->quote( $table ) .";


Или как тогда поступать в этом случае? 
    


Ответы

Ответ 1



Начнем с заблуждений. mysql_real_escape_string. многие поколения пхп кодеров считали и считают, что эта функция служит для защиты от неких инъекций. С такой точки зрения ее применение, конечно, оправдано. Но если однажды открыть для себя реальное предназначение этой функции, то станет ясно, что она здесь нужна как хипстеру андроид. Можно даже посмотреть действующий пример SQL инъекции, которой эта, как и любая другая функция искейпинга строк, не может помешать ни в малейшей степени. PDO::quote(). Уже гораздо лучше. В отличие от предыдущего варианта, который пройдет незамеченным, а потом пропустит инъекцию, quote() вызовет ошибку немедленно, поскольку выбирать данные из строки БД еще не научились - им нужно название таблицы. Некоторое время назад в комментариях к этой функции в мануале висел комментарий, причем с кучей положительных оценок, предлагавший оторвать от полученного значения добавленные к нему кавычки. Я посоветовал вместо этого оторвать руки предложившему, но сошлись на том, что оторвут только его комментарий. В итоге я написал свой, с объяснениями, как делать правильно. Итак, как правильно добавить имя таблицы или поля в запрос? Только через белый список. Т.е. после фильтрации через заранее прописанный в коде список Вариантов реализации может быть много, один из них предложен автором в комментариях - считать из БД все названия таблиц и запомнить их. Это, в принципе, может сработать. Некоторые фреймворки даже кэшируют эту информацию (например Yii). В случае с продвинутыми ORM названия поле-таблиц берутся из свойств соответствующего класса, опять же, прописанные вручную. Но если мы колупаемся по-старинке, выполняя запросы напрямую через PDO, то проще всего будет прописать доступные варианты прямо перед использованием, тем более что таких случаев не должно быть много - иначе у нас явные проблемы с проектированием. Плюс надо не забыть оформить имя поля или таблицы в соответствии с синтаксисом базы данных. Например, для mysql это будет заключение значения в backtick-и. В итоге получаем примерно такой код: if (!in_array($table, ["user","product","catalog"])); { throw new \Exception("Invalid table name!"); } $sql = "SELECT * FROM `$table` WHERE foo = ?" // далее как обычно Куда более частой является ситуация, когда нам надо выполнить запрос UPDATE динамически, если имена полей приходят, допустим, из $_POST. Принцип остается тем же: / список допустимых значений $allowed = ["name","surname","email"]; // инициализация массива для значений $params = []; // инициализация строки с парами `fieldname` = :placeholder $setStr = ""; // цикл по разрешенным полям foreach ($allowed as $key) { if (isset($_POST[$key]) && $key != "id") { $setStr .= " `$key` = ?,"; $params[] = $_POST[$key]; } } $setStr = rtrim($setStr, ","); $params[] = $_POST['id']; $pdo->prepare("UPDATE users SET $setStr WHERE id = ?")->execute($params);

Ответ 2



SELECT * FROM '".$tablevariable."' where ... Вот по полному mysqli_query($dblink, " SELECT * FROM '".$tablevariable."' ");

Комментариев нет:

Отправить комментарий