#php #mysql #pdo
#php #mysql #pdo
Вопрос:
Я реализую скрипт входа в систему, который работает некорректно. Я хочу, чтобы пользователи могли входить в систему либо под своими именами пользователей, либо по электронной почте. У меня есть две таблицы:
пользователь — содержит регистрационную информацию (имя пользователя, пароль, адрес электронной почты, isactive)
userprofile — содержит информацию профиля
ПРОБЛЕМЫ / ОШИБКИ:
- Вход в систему с адресами электронной почты не работает.
- Если вводится только имя пользователя, оставляя поле пароля пустым, пользователь все равно входит в систему независимо.
КОД (isactive проверяет, была ли активирована учетная запись пользователя после проверки электронной почты)
$uname = htmlspecialchars($_POST['username']);
$pword = htmlspecialchars($_POST['password']);
$isActive = 1;
$getId = 0;
try{
$stmt = $db->prepare("SELECT * FROM user WHERE username = :username OR email = :email AND password = :password AND isactive = :isactive");
$stmt->execute(array(':username' => $uname, ':email' => $uname, ':password' => $pword, ':isactive' => $isActive));
$numrows = $stmt->fetch(PDO::FETCH_ASSOC);
//to enable me count number of rows returned
$number = $stmt->fetch(PDO::FETCH_NUM);
$_SESSION['username'] = $numrows['username'];
$getId = $numrows['Id'];//get the id of the user
}catch(PDOException $ex){
echo 'QUERY ERROR: ' . $ex->getMessage();
}
/*this checks to see that the user has a profile (userId is a foreign key, thus user.Id = userprofile.userId always)*/
try{
$query = $db->prepare("SELECT * from userprofile WHERE userId = :userId");
$query->execute(array(':userId' => $getId));
$row = $query->fetchAll();
}catch(PDOException $exc){
echo 'QUERY ERROR: ' . $exc->getMessage();
}
//Check results and log user in
if(count($number) == 1 amp;amp; count($row) == 1){
header("Location: index.php");
}
else {$errorMessage = "<p style='color:#ff851b'>Invalid username or password</p>";}
Что мне нужно изменить, чтобы это заработало? Спасибо
Комментарии:
1. Мы не являемся краудсорсинговым сервисом отладки. По крайней мере, сузьте проблему до конкретной строки, по которой вы можете задать конкретный технический вопрос. Не просто загружайте страницу, полную кода, с самым расплывчатым описанием ошибки, и ожидайте, что мы отладим ее за вас.
2. Чтобы исправить вторую проблему, проверьте, указаны ли пароль и имя пользователя. Если нет, верните сообщение об ошибке.
Ответ №1:
Вы также можете легко включить количество строк в свой запрос:
И настройте запрос :
SELECT *, count(*) AS numrows
FROM user
WHERE (username = :username OR email = :email) AND
password = :password AND isactive = :isactive
Пожалуйста, внесите следующие изменения:
$stmt->execute(array(':username' => $uname,
':email' => $uname,
':password' => $pword,
':isactive' => $isActive));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(!$row){
throw new Exception('User not found');
}
//get user data
$numrows = (int)$row['numrows'];
if($numrows === 1){
//found a user
$_SESSION['username'] = $row['username'];
$id = $row['Id'];
}
Комментарии:
1. Спасибо. это хорошо. Но синтаксис в инструкции select выдал некоторые ошибки. Пришлось использовать этот …
SELECT * FROM user WHERE (username = :username OR email = :email) AND password = :password AND isactive = :isactive
Я думаю, что использование count(*) — самый простой способ подсчета возвращаемых строк в PDO. Хотя, если бы была такая функция, как mysql_num_rows, это было бы намного лучше.2. Ну, есть PDO ::rowCount, проблема в том, что иногда он не работает правильно с SELECT, это больше для затронутой строки, такой как UPDATE / DELTE / INSERT
Ответ №2:
Основная проблема, которую я вижу, заключается в следующем; необходимы некоторые скобки:
Перед:
$stmt = $db->prepare("SELECT * FROM user WHERE username = :username OR email = :email AND password = :password AND isactive = :isactive");
После:
$stmt = $db->prepare("SELECT * FROM user WHERE ((username = :username AND password = :password) OR (email = :email AND password = :password)) AND isactive = :isactive");
Кроме того, в этой строке вы присваиваете $uname
username
и email
— возможная ошибка копирования / вставки и здесь?
$stmt->execute(array(':username' => $uname, ':email' => $uname, ':password' => $pword, ':isactive' => $isActive));
Комментарии:
1. Спасибо. Это всего лишь одно поле, которое может принимать либо имя пользователя, либо адрес электронной почты, поэтому
$uname
назначается обоим2. да, я так думаю, но теперь я получаю сообщение об ошибке «неопределенный номер параметра» после изменения запроса. неправильно ли получать количество строк, возвращаемых следующим образом:
$number = $stmt->fetch(PDO::FETCH_NUM);
.?3. На данный момент я не могу протестировать, но из памяти вы могли бы попробовать:
$stmt->execute(...); $num = $stmt->fetch(PDO::FETCH_NUM); $number = $num[0];
Ответ №3:
Попробуйте
SELECT * FROM user WHERE (username = :username OR email = :email) AND password = :password AND isactive = :isactive"
в качестве запроса… Должно сработать…
Комментарии:
1. хорошо, спасибо. Я получаю сообщение об ошибке «неопределенный номер параметра» после настройки запроса. неправильно ли получать количество строк, подобных этому:
$number = $stmt->fetch(PDO::FETCH_NUM);
.