Не удается выяснить процедурную ошибку подготовленного оператора MySQL с использованием PHP

Я новичок в PHP и MySQL. На моем сервере установлена ​​версия 5.6 MySQL. Я использую процедурные операторы (не PDO, не OO). Это страница PHP на сайте, который я разрабатываю для пользователей, чтобы создать новую учетную запись. Странно то, что сообщение об ошибке возвращается на самой странице (https://mywebsite.com/create_account.php), а не в журнале ошибок на сервере.

* ВОТ СООБЩЕНИЕ ОБ ОШИБКЕ, ЧТО Я ПОЛУЧАЮ: *

Ошибка: ВСТАВИТЬ В пользователей (имя пользователя, пароль, имя_имя, имя_последнее, адрес_1, адрес_2, город, штат, почтовый_код, адрес электронной почты, номер_телефона, имя_на_карте, номер_основной_карты, номер_карты_ccv, срок действия_карты_мо, срок действия карты_год) ЗНАЧЕНИЯ (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) У вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, на предмет правильного синтаксиса для использования рядом с '?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '

* ВОТ МОЙ КОД, КОТОРЫЙ ВЫДАЕТ СООБЩЕНИЕ ОБ ОШИБКЕ: *

//
// Insert data into database
//

$sql = "INSERT INTO users (username, password, name_first, name_last, address_1, address_2, city, state, zip_code, email_address, phone_number, name_on_card, card_number_main, card_number_ccv, card_expire_mo, card_expire_yr) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = mysqli_prepare($link, $sql);
mysqli_stmt_bind_param($stmt, "ssssssssssssssss", $param_username, $param_password, $param_name_first, $param_name_last, $param_address_1, $param_address_2, $param_city, $param_state, $param_zip_code, $param_email_address, $param_phone_number, $param_name_on_card, $param_card_number_main, $param_card_number_ccv, $param_card_expire_mo, $param_card_expire_yr);
$param_username = $username;
$param_password = $password;
$param_name_first = $name_first;
$param_name_last = $name_last;
$param_address_1 = $address_1;
$param_address_2 = $address_2;
$param_city = $city;
$param_state = $state;
$param_zip_code = $zip_code;
$param_email_address = $email_address;
$param_phone_number = $phone_number;
$param_name_on_card = $name_on_card;
$param_card_number_main = $card_number_main;
$param_card_number_ccv = $card_number_ccv;
$param_card_expire_mo = $card_expire_mo;
$param_card_expire_yr = $card_expire_yr;
mysqli_stmt_execute($stmt);

Я прочитал руководство, как следует из сообщения об ошибке, но безрезультатно. Любая помощь будет принята с благодарностью. Спасибо.


person Mike B    schedule 11.07.2018    source источник
comment
@Uueerdo Это параметры, а не значения. Это должно быть действительным. (Так же, как это делает руководство)   -  person user3783243    schedule 11.07.2018
comment
Где вы делаете отчеты об ошибках? Вы уверены, что не передаете $sql вызову query(? Ошибка возникает в первом заполнителе, поэтому я думаю, что это должно быть связано с чем-то, что не знает, как обрабатывать привязки.   -  person user3783243    schedule 11.07.2018
comment
@user3783243 user3783243 Это не так. Он передает $sql вызову prepare, который затем выполняется позже. Вот как вы делаете привязку.   -  person Jonathan    schedule 11.07.2018
comment
ВНИМАНИЕ: Написать собственный уровень управления доступом непросто, и есть много возможностей сделать это серьезно неправильно. Пожалуйста, не пишите свою собственную систему аутентификации, когда любая современная среда разработки подобна Laravel поставляется с надежным встроенная система аутентификации. Как минимум следуйте рекомендуемым рекомендациям по обеспечению безопасности и никогда не храните пароли в виде обычного текста< /b> или слабый хеш, например SHA1 или MD5.   -  person tadman    schedule 11.07.2018
comment
Примечание. Объектно-ориентированный интерфейс mysqli значительно менее подробен, что упрощает чтение и проверку кода, и его нелегко спутать с устаревшим интерфейсом mysql_query. Прежде чем вы слишком увлечетесь процедурным стилем, стоит переключиться. Пример: $db = new mysqli(…) и $db->prepare("…") Процедурный интерфейс является артефактом эпохи PHP 4, когда был введен mysqli API, и его не следует использовать в новом коде.   -  person tadman    schedule 11.07.2018
comment
Нет причин создавать переменные, которые являются просто копиями других переменных. Просто привяжите к переменным, которые содержат правильные значения.   -  person tadman    schedule 11.07.2018
comment
@Jonathan Пожалуйста, прочитайте мой комментарий полностью, я знаю, как работают привязки. Если он делает if(...query($sql) хотя бы для проверки, это приведет к этой ошибке. У вас есть теория, почему prepare когда-либо жаловался на ???   -  person user3783243    schedule 11.07.2018
comment
Похоже, что запрос-заполнитель выполняется где-то еще, возможно, непреднамеренно. Какой бы избыточной ни была часть этого кода, это должно работать.   -  person tadman    schedule 11.07.2018
comment
@user3783243 user3783243 хорошая мысль. Я пропустил слово, читая ваш комментарий, и интерпретировал его по-другому. Я также не вижу ничего плохого в этом запросе/коде, кроме того, что кажется, что они хранят информацию о кредитной карте, что, по моему мнению, даже хуже, чем использование нехешированных паролей.   -  person Jonathan    schedule 11.07.2018


Ответы (1)


Переместить после объявления переменной bind stmt?

<?php

$sql = "INSERT INTO users (username, password, name_first, name_last, address_1, address_2, city, state, zip_code, email_address, phone_number, name_on_card, card_number_main, card_number_ccv, card_expire_mo, card_expire_yr) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = mysqli_prepare($link, $sql);

$param_username = $username;
$param_password = $password;
$param_name_first = $name_first;
$param_name_last = $name_last;
$param_address_1 = $address_1;
$param_address_2 = $address_2;
$param_city = $city;
$param_state = $state;
$param_zip_code = $zip_code;
$param_email_address = $email_address;
$param_phone_number = $phone_number;
$param_name_on_card = $name_on_card;
$param_card_number_main = $card_number_main;
$param_card_number_ccv = $card_number_ccv;
$param_card_expire_mo = $card_expire_mo;
$param_card_expire_yr = $card_expire_yr;


mysqli_stmt_bind_param($stmt, "ssssssssssssssss", $param_username, $param_password, $param_name_first, $param_name_last, $param_address_1, $param_address_2, $param_city, $param_state, $param_zip_code, $param_email_address, $param_phone_number, $param_name_on_card, $param_card_number_main, $param_card_number_ccv, $param_card_expire_mo, $param_card_expire_yr);
mysqli_stmt_execute($stmt);
person koalaok    schedule 11.07.2018
comment
Это неправильно. Взгляните на руководство. Он связывает параметр, а не значение. - person user3783243; 12.07.2018