2010-11-18 3 views
0

У меня есть код, предназначенный для запуска проверки в моей базе данных, чтобы узнать, уникально ли данное значение, и если да, вставьте его в db. Если он не уникален, повторите этот процесс, пока он не найдет уникальное значение.PHP do/while Подготовлено заявление с ошибкой

do { 
    // Generate a new user ID (15 numbers) and check to make sure it doesn't already exist. 
    $new_user_id = mt_rand(1000000000, 9999999999); 

    // Generate a fake Login Email address and check to make sure it doesn't already exist. 
    $new_username = rand_str(13, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'); 
    $new_username_email = 'BP' . $new_username . '@web.com'; 

    // Generate a new fake password 
    $new_password = rand_str(15, '[email protected]#$%^&*()'); 

    // Check to make sure the extremely random Username and user ID doesn't already exist in the database 
    // On the off chance that it does, we need to regenerate and try again. 

    $preparedStatement = $connection->prepare("SELECT user_id, username FROM `{$mysql_table}` WHERE user_id = :new_user_id OR username = :new_username"); 
    $preparedStatement->execute(array(':new_user_id' => $new_user_id, ':new_username' => $new_username_email)); 
    $result_2 = $preparedStatement->fetchAll(); 

    //TODO Not sure if this is actually working if there is a duplicate entry 
} while (!empty($result_2)); 

// Once it is unique, insert the values into the database 

$preparedStatement = $connection->prepare(
    "INSERT INTO `{$mysql_table}` (
     open_id, 
     user_id, 
     username, 
     password 
    ) VALUES (
     :open_id_value, 
     :user_id_value, 
     :username_value, 
     :password_value 
    )"); 

    if (!$preparedStatement->execute(array(
     ':open_id_value' => $_SESSION['user'], 
     ':user_id_value' => $new_user_id, 
     ':username_value' => $new_username_email, 
     ':password_value' => $new_password 
    ))) { 
     $arr = $preparedStatement->errorInfo(); 
        die(print_r($arr));        
    } else { 
    // Send the new user to the account settings page, where they can set up their account information 
     $_SESSION['new_user'] = 1; 
     //echo 'You are a new user!'; 
     header("Location: /account-settings/"); 
     exit;      
    } 

Проблема, что я получаю то, что значение, генерируемое mt_rand говорит, что это дубликат.

Array ([0] => 23000 [1] => 1062 [2] => Duplicate entry '2147483647' for key 1) 1 

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

Любые подсказки?

+2

2147483647 - это подозрительный идентификатор, так как он составляет 2^31 - 1. Что такое тип данных вашего столбца userID. Если это int, вы генерируете случайные числа выше максимально допустимого для этого столбца и пытаетесь вставить их. –

+0

Это int - я должен просто переключиться на char? –

+0

Я думаю, я мог бы сделать bigint ... позвольте мне попробовать, что –

ответ

3

Чтобы подробнее рассказать о моем комментарии ... Ваш скрипт генерировал случайное число, которое будет ~ 80% времени превышать максимальное значение int. Ваш запрос на проверку, если user_id уже был принят, вернет false (mysql позволяет запрашивать вне пределов диапазона столбца, он просто говорит, что нет записи с этим идентификатором), но тогда запрос на вставку будет терпеть неудачу, поскольку число будет свести к максимальному размеру INT. Чтобы исправить это, вы переключаетесь на BIGINT или ограничиваете свой случайный диапазон.

+0

Вы говорите, что скрипт будет проверять фактическое значение сгенерированного числа (например, 9999999999), чтобы узнать, существует ли это, почему он проходит, но затем число, которое нужно вставить, уменьшается один раз попытка вставить? –

+0

Точно. Я просто обновил ответ, чтобы быть более понятным. –

+0

Спасибо, чувак. Genius. Я мог бы поболтать об этом часами, и вы сделали это через несколько минут. Я бы проголосовал 8 раз, если бы мог –

0

Попробуйте изменить свой столбец идентификатора на BIGINT vs INT, поскольку он кажется, что вы пытаетесь создать случайное число выше емкости INT. Именно поэтому он понижает его до 2147483647, что является максимальным числом INT.

+0

Спасибо, получил это до сих пор - любые идеи относительно того, почему код не будет зацикливаться до тех пор, пока он не сгенерирует число меньше, чем 2147483647? –

0

Предел mt_rand(1000000000,2147483647); Тип данных int не может обрабатывать больше.

+0

Спасибо за вашу помощь - любые идеи относительно того, почему код не будет зацикливаться до тех пор, пока он не сгенерирует число меньше 2147483647? –

+0

Не в случае вышеуказанного кода. Он больше не будет превышать 2147483647. – stillstanding

0

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

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

Смежные вопросы