Просмотр поста

.
AlkatraZ
╭∩╮ (`-`) ╭∩╮
Следующий устаревший код, предназначенный для переделки у нас находится в строке 62
$from = $user_id ? $login : mysql_real_escape_string($name);

Это интересный и ВАЖНЫЙ момент, ибо он связан не с самим запросом, а с экранированием его данных, для предотвращения SQL инъекции и взлома Вашего сайта.
В старом коде для этого у нас была функция mysql_real_escape_string()
В PDO для достижения той же цели, можно пойти несколькими путями...

1) Простейший путь - это применить вместо устаревшей функции ее аналог $db->quote() и строка в этом случае будет выглядеть так:
$from = $user_id ? $login : $db->quote($name);
Однако $db->quote не полный аналог mysql_real_escape_string(), ибо он кроме экранирования кавычек внутри строки, еще и берет в кавычки саму строку. Следовательно нам надо будет переделать еще и запрос, убрав кавычки вокруг вставляемой переменной.

2) Другой и более правильный путь - это подготовленный запрос, который мы сейчас и будем реализовывать.
===
Итак, решил делать подготовленный запрос.
В начале я осмотрел дальнейший код на предмет, ГДЕ используется наша переменная $from и нашел нужный запрос, который в строке 120 и который надо переделать на подготовленное выражение. Для этого применяем метод $db->prepare() и заменяем все переменные в запросе на простые плейсхолдеры ? (знак вопроса). Есть еще именованные плейсхолдены, но их рассмотрим отдельно.
Старый код запроса временно где-то сохраняем, ибо нам понадобятся оттуда переменные.
После переделки на подготовленный запрос, код будет выглядеть так:
$stmt = $db->prepare("INSERT INTO `guest` SET
  `adm` = ?,
  `time` = ?,
  `user_id` = ?,
  `name` = ?,
  `text` = ?,
  `ip` = ?,
  `browser` = ?,
  `otvet` = ''
");

Обратите внимание на строку `otvet` = '', там передается пустое значение, поэтому я не стал ставить плейсхолдер а применил прямой запрос. То же самое можно делать, если передаете фиксированное числовое значение, к примеру `otvet` = 5
А для всех "опасных" данных, нужны плейсхолдеры.

Но это пока только подготовленное выражение, которое ничего не добавит в базу и которому мы пока не передали никаких данных. займемся этим. Нам нужно передать подготовленному запросу реальные данные и запустить его на выполнение (вставить запись в базу данных). Для этого применяем $stmt->execute(); в который в виде массива передаются наши данные, которые мы заменили плейсхолдерами.
ОЧЕНЬ ВАЖНО, чтоб данные в массиве находились именно в той последовательности, как у нас размещены плейсхолдеры, не перепутайте!
В итоге сравним что было и что стало:

СТАРЫЙ ЗАПРОС:
mysql_query("INSERT INTO `guest` SET
  `adm` = '$admset',
  `time` = '" . time() . "',
  `user_id` = '" . ($user_id ? $user_id : 0) . "',
  `name` = '$from',
  `text` = '" . mysql_real_escape_string($msg) . "',
  `ip` = '" . core::$ip . "',
  `browser` = '" . mysql_real_escape_string($agn) . "',
  `otvet` = ''
");


НОВЫЙ ПОДГОТОВЛЕННЫЙ ЗАПРОС
$db->prepare("INSERT INTO `guest` SET
  `adm` = ?,
  `time` = ?,
  `user_id` = ?,
  `name` = ?,
  `text` = ?,
  `ip` = ?,
  `browser` = ?,
  `otvet` = ''
")->execute([
  $admset,
  time(),
  ($user_id ? $user_id : 0),
  $from,
  $msg,
  core::$ip,
  $agn,
]);


ВАЖНО: в подготовленном запросе не надо экранировать данные, то, что мы делали с помощью mysql_real_escape_string(). Более того, если вспомним строку 62, мы с нее тоже должны убрать экранировку.

Итого, после доработки в репозитории у нас следующее:
Строка 62: https://github.com/john-cms/jo ... p#L62
Подготовленный запрос: https://github.com/john-cms/jo ... -L137

Можно работать дальше