Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 27.02.2019, 01:01
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Фокус с синтаксисом БД
Привет всем! Нужно через с помощью php добавлять в БД (MySQL) новые строки (работаю с MySQL 5.7 и PHP 7.1). Сделал функцию:
function add_task($link, array $post, array $files, int $user_id): bool {
    $name = $post['project'];
    $category_id = $post['name'];
    $expires_at = !empty($post['date']) ? date_format(date_create($post['date']), 'Y-m-d') : NULL;

    foreach($files as $file) {
        $file_path = $file['name'] ? __DIR__ . '\\'. $file['name'] : NULL;
    }

    $sql_add_task = "INSERT INTO tasks(user_id, category_id, name, expires_at, file_path) VALUES($user_id, $category_id, $name, $expires_at, $file_path)";

    $result = mysqli_query($link, $sql_add_task);

    if(!$result) {
        die("Ошибка MySQL: " . mysqli_error($link));
    }

    return $result;
}

А вот структура таблицы, куда нужно будет вставлять строки:
CREATE TABLE tasks (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
category_id INT,
name CHAR(128) NOT NULL,
created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
done_at DATE NULL DEFAULT NULL,
status INT DEFAULT 0,
expires_at DATE NULL DEFAULT NULL,
file_path CHAR(128)
);

Проблема в строке с запросом INSERT. Он обёрнут в " ". В нём $category_id и $name обязательны, это строки. А $expires_at и $file_path - факультативны, если они есть - это строки, если нет - тогда NULL. Если в таком виде запустить функцию, то возникает ошибка:
Ошибка MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'народ с балкона золотыми монетами, 2019-02-28, W:\d' at line 2

var_dump выводит такую строку запроса:
string(251) "INSERT INTO tasks(user_id, category_id, name, expires_at, file_path) VALUES(1, 1, Осыпать народ с балкона золотыми монетами, 2019-02-28, W:\domains\216812-doingsdone\1024-31-snowpark.psd)"

Проблема в том, что переменные name, expires_at, file_path изначально типа string. А учитывая, что весь вопрос обёрнут тоже в " ", внутри кавычки вокруг значений, в которые превращаются переменные, я так понимаю, убираются. В итоге - ошибка.

Оборачивать переменные в ' ' - не выход, ибо вместо некоторых может быть NULL - опять ошибка. Подскажите, как быть в такой ситуации

Последний раз редактировалось Alessio18911, 27.02.2019 в 01:30.
Ответить с цитированием
  #2 (permalink)  
Старый 27.02.2019, 03:47
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

$expires_at = !empty($post['date']) ? date_format(date_create($post['date']), 'Y-m-d') : NULL;

А входные данные обрабатываются или как есть? А если что пришло тому и верим, то !empty(" ") есть истина, и какая же в таком случае дата должна быть создана?

Строковые значения всегда и везде заключаются в кавычки. Только вы используете РНР 7, а в тоже время не используете возможностей mysqli. Вы думаете она сама по себе занимается экранированием в запросах? Как бы не так. А ведь есть же mysqli_stmt:repare, mysqli_stmt::bind_param и т.д., которые как раз и решат ваши проблемы, и обезопасят запрос.

Последний раз редактировалось laimas, 27.02.2019 в 06:39.
Ответить с цитированием
  #3 (permalink)  
Старый 27.02.2019, 09:55
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Спасибо огромное, проблема действительно разрешилась! Единственное, всё же непонятным осталось, почему в изначальном случае в строке запроса кавычки вокруг string после интерполяции переменных убирались.
Ответить с цитированием
  #4 (permalink)  
Старый 27.02.2019, 10:02
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,723

Сообщение от Alessio18911
Единственное, всё же непонятным осталось, почему в изначальном случае в строке запроса кавычки вокруг string после интерполяции переменных убирались.
А почему они остаться-то должны были?
Кавычки указывают границу строки и не входят в саму строку.
Ответить с цитированием
  #5 (permalink)  
Старый 27.02.2019, 12:17
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 498

Alessio18911,
Код:
$ php -r 'echo "строка\n";'
строка
$ php -r 'echo "\"строка в кавычках\"\n";'
"строка в кавычках"
Ответить с цитированием
  #6 (permalink)  
Старый 28.02.2019, 20:08
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Сообщение от Nexus Посмотреть сообщение
А почему они остаться-то должны были?
Кавычки указывают границу строки и не входят в саму строку.
Ну, я проводил аналогию, если писать запросы без переменных. Тогда бы он ведь выглядел так:
INSERT INTO tasks(user_id, category_id, name, expires_at, file_path) VALUES(1, 1, 'Напасть на след бременских музыкантов', '2019-05-05', '');
Вот я и подумал, что кавычки должны сохраниться..
Хорошо, а можно было бы выкрутиться в данном ситуации БЕЗ функций mysqli, типа mysqli_prepare и т.д.? И как? Ведь в коде строки вставляются через переменные....
Ответить с цитированием
  #7 (permalink)  
Старый 28.02.2019, 20:09
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Сообщение от Белый шум Посмотреть сообщение
Alessio18911,
Код:
$ php -r 'echo "строка\n";'
строка
$ php -r 'echo "\"строка в кавычках\"\n";'
"строка в кавычках"
Ага, спасибо! )
Ответить с цитированием
  #8 (permalink)  
Старый 01.03.2019, 12:40
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от Alessio18911
можно было бы выкрутиться в данном ситуации БЕЗ функций mysqli, типа mysqli_prepare и т.д.? И как?
Сообщение от Alessio18911
Ага, спасибо! )
Можно, но средствами не РНР, а mysqli - mysqli_real_escape_string. Вот только зачем это делать. Подготовленный запрос может использовать метки вместо самих переменных (в mysqli есть только не именованные метки), и подготовленный единожды будет использоваться, подставляя в него значения следующего запроса. В случае подготовленных запросов экранированием занимается сам драйвер, без явного указания этого в запросе. А экранирование запросов нужно делать обязательно, и не только ради "борьбы" с кавычками, а для того чтобы обезопасить запрос.
Ответить с цитированием
  #9 (permalink)  
Старый 04.03.2019, 12:39
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Понятно. Очень признателен за детальные и понятные ответы. Спасибо!
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Установить фокус в инпут ДашаДаша Angular.js 2 23.01.2019 10:24
Как перевести фокус на следующий элемент? Shitbox2 jQuery 3 03.11.2012 15:57
2 гридов и фокус bdfy1 ExtJS 1 17.06.2011 03:49
Как вернуть фокус в окно редактирования? Roman Koff Общие вопросы Javascript 1 02.08.2010 12:35
Как убрать выделение в Опере у div, получившего фокус ? spa_2002 Opera, Safari и др. 5 03.09.2009 10:42