Запрос PDO MySQL без учета регистра чувствителен к регистру И SQLSTATE [23000]: нарушение ограничения целостности: 1062 Дубликат записи для ключа «user_name»

Впервые я заметил эту проблему, когда кто-то (ранее на этой неделе) смог зарегистрировать две учетные записи, используя один и тот же адрес электронной почты (с учетом регистра). Я исправил это, добавив strtolower при регистрации и на данный момент добавил LOWER для запроса (я думаю, мне следует сделать все ранее существующие электронные письма в базе данных строчными буквами, поэтому я не нужно использовать LOWER в запросе).

Часть, с которой у меня сейчас проблемы (я пытаюсь понять это уже около 5 дней), заключается в том, чтобы выяснить, как запросить без учета регистра существующие имена пользователей в базе данных и сравнить (опять же случай нечувствительны) к новым именам пользователей во время регистрации.

Это не работает (и я думал, что запрос по умолчанию нечувствителен к регистру, но оказалось, что это не так?), потому что я продолжаю получать это SQLSTATE[23000]: нарушение ограничения целостности: 1062 повторяющаяся запись '[ имя, указанное при регистрации здесь]' для ключа 'user_name'

Эта часть кажется, по крайней мере мне, простой, она уникальна, поэтому я не могу иметь два одинаковых имени пользователя в базе данных.

Проблема, с которой я сталкиваюсь, - это запрос без учета регистра или, может быть, это сопоставление имен пользователей в базе данных (но я уже пробовал десятки. Единственное сопоставление, которое, кажется, делает то, для чего оно предназначено (хотя и не то, что мне нужно) < strong>latin1_bin, что позволит использовать имена пользователей с учетом регистра (например, Duke, duke, DuKE), и если кто-то еще попытается зарегистрировать то же самое, им это не будет разрешено (например, DuKE не может зарегистрироваться, если DuKE существует, но может зарегистрировать duKe ) Это здорово (возможно, я воспользуюсь этим позже для другого моего дрянного сайта, в основном для хобби и чтения книг), но сейчас мне нужно иметь возможность запретить пользователю регистрировать одни и те же имена с вариантами заглавных и строчные буквы (например, если зарегистрирован «герцог», то кто-то другой, пытающийся зарегистрировать «герцога», не сможет это сделать).

Все вышеперечисленное может показаться повторяющимися вопросами, найденными в другом месте, но я считаю, что перепробовал все ответы, представленные в похожих вопросах (я десятки раз менял код, чтобы он соответствовал ответам, но ни один из них не дает разные результаты) . Я также пытался изменить параметры сортировки (десятки раз) в базе данных для имен пользователей (в настоящее время это utf8mb4_general_ci).

Каждый раз, когда я пробую сценарий регистрации, он разрешает повторяющиеся имена пользователей (например, Duke проходит, даже если Duke уже находится в базе данных) для прохождения, а затем (что, как я полагаю, ожидается) я получаю SQLSTATE [23000]: ограничение целостности нарушение: 1062 Дублирующаяся запись.

Если бы кто-нибудь здесь мог дать некоторое представление о том, что я делаю неправильно, я был бы очень благодарен! Спасибо! Код ниже:

<?php

require_once 'dbconfig.php';

if($user->is_loggedin()!="")
{
$user->redirect('home.php');
}

if(isset($_POST['btn-signup']))
{
$uname = trim($_POST['txt_uname']);
$umail = strtolower(trim($_POST['txt_umail']));
$upass = trim($_POST['txt_upass']); 

if($uname=="")  {
    $error[] = "provide username !";    
}
else if($umail=="") {
    $error[] = "provide email id !";    
}
else if(!filter_var($umail, FILTER_VALIDATE_EMAIL)) {
    $error[] = 'Please enter a valid email address !';
}
else if($upass=="") {
    $error[] = "provide password !";
}
else if(strlen($upass) < 6){
    $error[] = "Password must be atleast 6 characters"; 
}
else
{
    try
    {

        $stmt = $DB_con->prepare("SELECT user_name,user_email FROM users 
WHERE user_name = :uname OR LOWER(user_email) = LOWER(:umail)");
        $stmt->execute(array(':uname'=>$uname, ':umail'=>$umail));
        $row=$stmt->fetch(PDO::FETCH_ASSOC);

        if($row['user_name']==$uname) {
            $error[] = "sorry username already taken !";
        }
        else if($row['user_email']==$umail) {
            $error[] = "sorry email id already taken !";
        }
        else
        {
            if($user->register($fname,$lname,$uname,$umail,$upass)) {

                $user->redirect('sign-up.php?joined');
            }
        }
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
    }
}   
}

?>

person Luke NB    schedule 29.07.2018    source источник
comment
хорошо, я скину фрагмент, ниже. Надеюсь, поможет   -  person Ifeanyi Amadi    schedule 29.07.2018


Ответы (1)


Попробуйте этот код

$stmt = $DB_con->prepare("SELECT user_name,user_email FROM users WHERE user_name LIKE :uname OR user_email LIKE :umail ");

$stmt->execute([':uname' => $uname, ':umail' => $umail]);

$found = false;
$inRecord = [];

while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
    $__uname = $row['user_name'];
    $__umail = $row['user_email'];

    if ($__uname == $uname || strtolower($__uname) == strtolower($uname))
    {
        $inRecord['user_name'] = true;
    }

    if ($__umail == $umail || strtolower($__umail) == strtolower($umail))
    {
        $inRecord['user_email'] = true;
    }

    if (count($inRecord) > 0)
    {
        $found = true;
        break;
    }
}

if ($found === true)
{
    if (isset($inRecord['user_name']))
    {
        echo "Username exists!";
    }

    if (isset($inRecord['user_email']))
    {
        echo "Email exists!";
    }
}
else
{
    // register here...
}

Будет выводиться только в том случае, если совпадение найдено.

Имя пользователя существует! Электронная почта существует!

person Ifeanyi Amadi    schedule 29.07.2018