Скрипт входа с использованием PDO

#php #mysql #pdo

#php #mysql #pdo

Вопрос:

Я реализую скрипт входа в систему, который работает некорректно. Я хочу, чтобы пользователи могли входить в систему либо под своими именами пользователей, либо по электронной почте. У меня есть две таблицы:

пользователь — содержит регистрационную информацию (имя пользователя, пароль, адрес электронной почты, isactive)

userprofile — содержит информацию профиля

ПРОБЛЕМЫ / ОШИБКИ:

  1. Вход в систему с адресами электронной почты не работает.
  2. Если вводится только имя пользователя, оставляя поле пароля пустым, пользователь все равно входит в систему независимо.

КОД (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); .