Имена таблиц и столбцов НЕ МОГУТ заменяться параметрами в PDO.
В этом случае вы просто захотите отфильтровать и очистить данные вручную. Один из способов сделать это - передать сокращенные параметры в функцию, которая будет динамически выполнять запрос, а затем использовать switch()
инструкцию для создания белого списка допустимых значений, которые будут использоваться для имени таблицы или имени столбца. Таким образом, никакой пользовательский ввод никогда не входит непосредственно в запрос. Так, например:
function buildQuery( $get_var )
{
switch($get_var)
{
case 1:
$tbl = 'users';
break;
}
$sql = "SELECT * FROM $tbl";
}
Не оставляя регистр по умолчанию или используя регистр по умолчанию, который возвращает сообщение об ошибке, вы гарантируете, что используются только те значения, которые вы хотите использовать.
array('u'=>'users', 't'=>'table', 'n'=>'nonsensitive_data')
и т. Д.)default
. Если вы используете этот шаблон, вы должны либо пометить один из своихcase
default
default: throw new InvalidArgumentException;
if ( in_array( $tbl, ['users','products',...] ) { $sql = "SELECT * FROM $tbl"; }
. Спасибо за идею.mysql_real_escape_string()
. Может быть, здесь я могу сказать это без того, чтобы кто-то запрыгнул и сказал: «Но вам это не нужно с PDO»Чтобы понять, почему не работает привязка имени таблицы (или столбца), вам необходимо понять, как работают заполнители в подготовленных выражениях: они не просто подставляются в строки (с подходящим экранированием), а полученный SQL выполняется. Вместо этого СУБД с просьбой «подготовить» оператор предлагает полный план запроса о том, как он будет выполнять этот запрос, включая таблицы и индексы, которые он будет использовать, которые будут одинаковыми независимо от того, как вы заполняете заполнители.
План
SELECT name FROM my_table WHERE id = :value
будет таким же, каким вы его заменяете:value
, но внешне похожий планSELECT name FROM :table WHERE id = :value
не может быть спланирован, потому что СУБД понятия не имеет, из какой таблицы вы на самом деле собираетесь выбирать.Это не та библиотека абстракций, как PDO, которая может или должна обходиться, так как она бы победила 2 ключевые цели подготовленных операторов: 1) позволить базе данных заранее решить, как будет выполняться запрос, и использовать тот же планировать несколько раз; и 2) предотвратить проблемы безопасности, отделив логику запроса от переменной ввода.
источник
TOP
/LIMIT
/OFFSET
, так что это было бы немного неуместно в качестве функции.Я вижу, что это старый пост, но я нашел его полезным и решил поделиться решением, аналогичным предложенному @kzqai:
У меня есть функция, которая получает два параметра, как ...
Внутри я проверяю массивы, которые я настроил, чтобы убедиться, что доступны только таблицы и столбцы с «благословенными» таблицами:
Тогда проверка PHP перед запуском PDO выглядит так ...
источник
$pdo->query($sql)
Использование первого не является более безопасным, чем второе, вам необходимо санировать входные данные, независимо от того, является ли это частью массива параметров или простой переменной. Так что я не вижу ничего плохого в использовании последней формы с
$table
, при условии, что вы убедитесь, что содержимое$table
безопасно (alphanum plus подчеркивания?) Перед его использованием.источник
(Поздний ответ, обратитесь к моей записке).
То же правило применяется при попытке создать «базу данных».
Вы не можете использовать подготовленный оператор для привязки базы данных.
То есть:
не будет работать. Вместо этого используйте список надежных отправителей.
Примечание: я добавил этот ответ (как вики сообщества), потому что он часто использовался для закрытия вопросов, где некоторые люди публиковали вопросы, подобные этим, пытаясь связать базу данных, а не таблицу и / или столбец.
источник
Часть меня интересует, не могли бы вы предоставить свою собственную функцию очистки, такую простую:
Я действительно не продумал это, но кажется, что удаление всего, кроме символов и подчеркиваний, может сработать.
источник
MyLongTableName
легко читать правильно, но если вы проверите сохраненное имя, оно (вероятно) будетMYLONGTABLENAME
не очень читабельным, поэтомуMY_LONG_TABLE_NAME
фактически более читабельным.Select * From $table
. Белый список или строгое соответствие шаблону (например, «имена, начинающиеся с отчета_, за которыми следуют только от 1 до 3 цифр») здесь действительно важно.Что касается основного вопроса в этой теме, то в других статьях было ясно, почему мы не можем привязать значения к именам столбцов при подготовке операторов, поэтому вот одно из решений:
Выше приведен только пример, поэтому, разумеется, copy-> paste не будет работать. Отрегулируйте под свои нужды. Теперь это может не обеспечивать 100% -ную безопасность, но позволяет некоторый контроль над именами столбцов, когда они «входят» как динамические строки и могут быть изменены на стороне пользователя. Кроме того, нет необходимости создавать какой-либо массив с именами и типами столбцов таблицы, поскольку они извлекаются из information_schema.
источник