Generalnie nie jest możliwe generowanie sekwencji z elementami zarówno unikalnymi, jak i losowymi:oczywiście, aby był unikalny, algorytm musi brać pod uwagę wcześniej wygenerowane elementy w sekwencji, więc następne nie będą tak naprawdę losowe.
Dlatego najlepiej byłoby wykryć kolizje i po prostu spróbować ponownie (co w konkretnym przypadku może być bardzo kosztowne).
Jeśli jesteś ograniczony do 7 znaków, niewiele możesz zrobić powyżej:
$allowed_chars = 'abcdefghijklmnopqrstuvwxz';
$allowed_count = strlen($allowed_chars);
$password = null;
$password_length = 7;
while($password === null || already_exists($password)) {
$password = '';
for($i = 0; $i < $password_length; ++$i) {
$password .= $allowed_chars{mt_rand(0, $allowed_count - 1)};
}
}
To powinno ostatecznie dać ci nowe hasło.
Jednak w podobnych przypadkach, z którymi się spotkałem, zwykle wybieram większy rozmiar hasła, który jest również rozmiarem reprezentacji szesnastkowej popularnej funkcji skrótu (np. md5
). Wtedy możesz sobie to ułatwić i zmniejszyć podatność na błędy:
$password = time(); // even better if you have some other "random" input to use here
do {
$password = md5(time().$password);
}
while (already_exists($password));
Ma to również tę dodatkową zaletę, że przestrzeń sekwencji jest większa, a zatem będzie mniej kolizji. Możesz wybrać rozmiar funkcji mieszającej zgodnie z oczekiwaną liczbą haseł, które wygenerujesz w przyszłości, aby "zagwarantować" niskie prawdopodobieństwo kolizji, a tym samym mniej wywołań do potencjalnie drogiego already_exists
funkcja.