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

122
28 июля 2019, 15:30

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

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

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

Answer 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);
Answer 2
 SELECT * FROM '".$tablevariable."' where ... 

Вот по полному

 mysqli_query($dblink, " SELECT * FROM '".$tablevariable."' ");
READ ALSO
Абсолютный путь к папке на уровень выше

Абсолютный путь к папке на уровень выше

Есть главная папка с проектом в которой находится папка конфига, в конфиге есть php файл, в котором я ищу абсолютный путь к этой папке так:

112
парсинг с библиотекой Simple HTML DOM

парсинг с библиотекой Simple HTML DOM

в парсере есть функция file_get_html, если в нее передать адрес

135
Получение данных из google spreadsheet (php)

Получение данных из google spreadsheet (php)

Нужно получить выборку данных из гугл таблицы по дате, все даты расположены в порядке убывания в одной колонке

113
Ошибка cannot open source file “stdafx.h”

Ошибка cannot open source file “stdafx.h”

Мне достались исходники небольшого проекта из нескольких файловПри открытии его в visual studio еще до начала компиляции в редакторе кода в каждом...

143