Nói chung là không thể tạo chuỗi có cả phần tử duy nhất và ngẫu nhiên:rõ ràng là để là duy nhất, thuật toán phải tính đến các phần tử đã tạo trước đó trong chuỗi, vì vậy các phần tử tiếp theo sẽ không thực sự là ngẫu nhiên.
Do đó, đặt cược tốt nhất của bạn là phát hiện va chạm và chỉ cần thử lại (có thể rất tốn kém trong trường hợp cụ thể của bạn).
Nếu bạn chỉ có 7 ký tự, bạn không thể làm gì ở trên:
$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)};
}
}
Điều này cuối cùng sẽ cung cấp cho bạn một mật khẩu mới.
Tuy nhiên, trong những trường hợp tương tự mà tôi gặp phải, tôi thường chọn kích thước mật khẩu lớn hơn, kích thước này cũng giống như kích thước của biểu diễn hex của một hàm băm phổ biến (ví dụ:md5
). Sau đó, bạn có thể tự làm cho mình dễ dàng hơn và ít mắc lỗi hơn:
$password = time(); // even better if you have some other "random" input to use here
do {
$password = md5(time().$password);
}
while (already_exists($password));
Điều này cũng có một lợi thế nữa là không gian trình tự lớn hơn, do đó sẽ ít va chạm hơn. Bạn có thể chọn kích thước của hàm băm theo số lượng mật khẩu dự kiến mà bạn sẽ tạo trong tương lai để "đảm bảo" xác suất va chạm thấp và do đó ít lệnh gọi đến already_exists
có thể đắt hơn chức năng.