Выход из цикла и разделение ответственностей при генерации идентификатора


Исходный код

while(!$a){
    $rd = rand(1,999999);
    $mdrd = md5($rd);
    db_query("SELECT * FROM players WHERE mdid = '$mdrd' LIMIT 1;");
    $fla = db_fetch();
    if(empty($fla))
        $a=1;
}

Что не так в исходном коде

Здесь опять, как и в прошлый раз, для выполнения как минимум одной попытки генерации идентификатора применён финт ушами.

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

Вариант рефакторинга

while (true){
    $rd = rand(1,999999);
    $mdrd = md5($rd);
    db_query("SELECT mdid FROM players WHERE mdid = '$mdrd' LIMIT 1;");
    $fla = db_fetch();
    if (empty($fla))
        break;
}

Также нетрудно видеть, что код внутри цикла выполняет две обязанности:

  • сгенерировать случайный идентификатор
  • проверить наличие в БД пользователя с указанным идентификатором

Неплохо такие вещи прятать в отдельные функции:

function generate_random_id()
{
    return md5(rand(1, 999999));
}
function is_user_exists($md5_id)
{
    db_query("SELECT mdid FROM players WHERE mdid = '$mdrd' LIMIT 1;");
    $fla = db_fetch();
    return !empty($fla);
}
while (true) {
    $mdrd = generate_random_id();
    if (!is_user_exists($mdrd)) 
        break;
}

В реале у нас должна быть функция получения пользователя по идентификатору, за счёт чего реализация is_user_exists станет немного проще (а то сейчас функция is_user_exists снова знает, как делать две разных вещи: получить пользователя с заданным идентификатором и проверить, что он не пустой):

function get_user_by_id($md5_id)
{
    db_query("SELECT mdid FROM players WHERE mdid = '$mdrd' LIMIT 1;");
    return db_fetch();
}
function is_user_exists($md5_id)
{
    return !empty(get_user_by_id($md5_id))
}

Теория