Я видел много ответов о входе в php с помощью имени пользователя или электронной почты, но я не могу найти разрешение «Mysqli Prepare Statement», все они использовали PDO ...
У меня вопрос, почему я не могу использовать два ?
для выбора имени пользователя или адреса электронной почты?
Мой код здесь:
База данных
table user
--id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
--username varchar(20),
--password varchar(255),
--email varchar(30),
html
<form action = "login.php" id = "login_form" method = "post">
<input type = "text" name = "account" placeholder = "username or email" />
<input type = "password" name = "password" placeholder = "password" />
<div class = "login_submit">
<button type = "submit" name = "submit">Login</button>
</div>
</form>
PHP
<?php
$con = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT);
$con->query('SET CHARACTER SET utf8');
if (isset($_POST['submit'])) {
$account = $_POST['account'];
$get_password = $_POST['password'];
$login_query = 'SELECT username,password,email FROM user WHERE username = ? OR email = ?';
$login_stmt = $con->stmt_init();
if ($login_stmt->prepare($login_query)) {
$login_stmt->bind_param('ss', $account, $account);
$login_stmt->execute();
$login_stmt->bind_result($username, $password, $email);
$login_result = $login_stmt->get_result();
while ($login_row = $login_result->fetch_assoc()) {
$check_password = $login_row['password'];
}
} else {
echo 'Login Error';
exit();
}
if ($login_result->num_rows == 0) {
$account_error = $lang_account_not_exist;
$login_permit = false;
} elseif (!password_verify($get_password, $check_password)) {
$password_error = $lang_wrong_password;
$login_permit = false;
}
РЕДАКТИРОВАТЬ
bind_result($username, $password, $email);
Они заполнители. Когда mysqli (и PDO, поскольку он также может использовать синтаксис?) Выполняет запрос, он сообщает вашей базе данных, что нужно использовать значения, которые вы передаете в bind_param вместо вопросительных знаков, по порядку.
В вашей базе данных есть username
и email
, оба установлены на то, что пользователь ввел в $_POST['account']
.
Сделайте некоторую проверку ошибок. Добавьте ini_set('display_errors', 1); ini_set('log_errors',1); error_reporting(E_ALL); mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
в начало вашего скрипта. Это заставит любые ошибки mysqli_
генерировать исключение, которое вы можете увидеть в браузере, а другие ошибки также будут видны в вашем браузере.
Может быть, сейчас самое время обратиться к руководству? php.net/manual/en/mysqli-stmt.bind-param.php
$login_stmt->bind_result($password);
не требуется, что может вызвать другие проблемы
Я не вижу кода, который действительно устанавливает соединение с базой данных в том, что вы нам показываете. Вы подключаетесь к базе данных ?? mysqli_connect()
@RiggsFolly Я добавил этот код, $ con
Проблема с mysqli_stmt::bind_result()
. Вы выбираете 3 столбца, но связываете только 1 переменную.
@aynber Я не думаю, что это вообще должно быть там, или я ошибаюсь
Уверен, что $login_stmt = $con->stmt_init();
тоже не нужен
@RiggsFolly Я не использую mysqli, поэтому не уверен. Я думаю, что OP должен либо полностью отказаться от него, либо передать правильное количество переменных.
@aynber Поскольку мой проект слишком велик, чтобы заменить mysqli на PDO, я хочу знать, как он работает на mysqli ...
@RiggsFolly stmt_init()
- это функция, которую я нашел здесь: Ссылка на сайт, так что .. она не нужна?
@Dormilich извини, это моя вина, я имею в виду why I can not use two ?
@ carry0987 Что говорится в сообщении об ошибке?
Ага, правильно сформулированный вопрос меняет ответ. Вы может используете 2 ?
в своем операторе подготовки. Проблема не в этом. Подготовка / bind_param / execute работает нормально, но (как упоминалось ранее) ошибка возникает из-за привязки bind_result
1 переменной к 3 столбцам.
@Dormilich он сказал PHP Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
@aynber Я добавляю 3 переменные, теперь она не сообщает об ошибках, но все равно не могу войти в систему ...
Если ошибки нет, вам нужно будет устранить неполадки. Зарегистрируйте / echo / var_dump в своем коде, чтобы узнать, куда он идет и что делает, и что содержат ваши переменные.
@ carry0987 Ознакомьтесь с Руководством по использованию mysqli_stmt::bind_result()
. Смешанные стратегии выборки могут привести к неожиданным результатам.
@Dormilich Я увидел проблему, я использую неопределенную переменную с именем $ login_username, теперь я исправил это, большое спасибо!
@aynber Я использую var_dump и увидел проблему, спасибо за напоминание!
Вероятно, ваша проблема НЕ в
$login_stmt->bind_param('ss', $account, $account);
Как вы думаете.
Выглядит нормально, пока не ваш $_POST['account']
- это массив, а не отдельная переменная, в чем я сомневаюсь. В этом случае он там не сработает. Но ваш оператор WHERE и bindparam выглядят правильно
Однако это неверно:
$login_stmt->bind_result($password);
Потому что вы пытаетесь привязать только одну переменную, и в вашем операторе SELECT (SELECT username,password,email
) возвращаются 3 столбца.
Поскольку вам действительно не нужны email
и username
в вашем коде, просто измените свой запрос следующим образом:
$login_query = 'SELECT password FROM user WHERE username = ? OR email = ?';
и это должно работать
"почему я могу использовать два
?
..." => Нет смысла разрешать только один?
в подготовленном операторе.