ループ、文字列の連結、rand() への複数回の呼び出しなどの汚れた/コストのかかるものを使用せずに、きれいで読みやすい方法でそれを行うことができます。また、次を使用することをお勧めしますmt_rand()
。
function createRandomString($length)
{
$random = mt_rand(0, (1 << ($length << 2)) - 1);
return dechex($random);
}
どのような場合でも文字列を正確な長さにする必要がある場合は、16 進数をゼロで埋めてください。
function createRandomString($length)
{
$random = mt_rand(0, (1 << ($length << 2)) - 1);
$number = dechex($random);
return str_pad($number, $length, '0', STR_PAD_LEFT);
}
「理論的なバックドロー」は、PHP の機能に制限されているということですが、その場合、これはより哲学的な問題です;)とにかくそれを見てみましょう:
- PHP は、このように 16 進数として表現できるものに制限があります。これは
$length <= 8
、少なくとも32 ビット システムでは可能であり、PHP の制限は 4.294.967.295 である必要があります。
- PHP の乱数ジェネレーターにも最大値があります。
mt_rand()
少なくとも32 ビット システムでは、2.147.483.647 である必要があります。
- したがって、理論的には 2.147.483.647 ID に制限されます。
話題に戻りdo { (generate ID) } while { (id is not uniqe) } (insert id)
ましょう - 直観的な人には欠点が 1 つあります。
欠点:検証は悲観的です。このように行うには、常にデータベースでのチェックが必要です。十分なキースペース (たとえば、10,000 エントリに対して長さ 5) があると、衝突が頻繁に発生する可能性はほとんどなくなります。これは、UNIQUE KEY エラーの場合にのみデータを保存して再試行するだけで、リソースの消費が比較的少なくて済む可能性があるためです。
欠陥: ユーザー Aは、まだ取得されていないことが確認された ID を取得します。次に、コードはデータを挿入しようとします。しかしその間、ユーザー Bは同じループに入り、残念ながら同じ乱数を取得します。ユーザー Aはまだ保存されておらず、この ID はまだ空いていたからです。これで、システムはUser BまたはUser A のいずれかを保存し、2 番目の User を保存しようとすると、その間に同じ ID を持つ別のユーザーが既に存在します。
どのような場合でもその例外を処理する必要があり、新しく作成された ID で挿入を再試行する必要があります。悲観的なチェック ループ (再入力が必要) を維持しながらこれを追加すると、非常に醜く、コードを追跡するのが難しくなります。幸いなことに、これに対する解決策は、欠点に対する解決策と同じです。最初にそれを実行して、データを保存してみてください。UNIQUE KEY エラーの場合は、新しい ID で再試行してください。