こんにちはエンジニアのオータケです。
みなさんはWebサービスを開発している時に次のようなことを思ったことはありませんか?
「羅列された英数字がほしい」
「一時的にファイルに付けておきたい名前として適当な方法はないか」
「ダミーのユーザー名を生成したい」
このような状況に遭遇した方は必見です。
また、このような状況でなくても「ユニークなIDを生成したい」と思ったかたはぜひごらんください。
この記事では次のことについて解説しています。
[応用] 文字列のみ、数値のみでユニークなIDを出力したい
[応用] 文字列のみ、数値のみでユニークなIDを出力したい
[実践] パスワードとして使う?
では早速、見ていきましょう!
自動でユニークな値を生成するuniqidを使ってみよう
ユニークな値とは?
まず、本記事ではuniqid関数について解説をします。
その関数を一言で説明するとユニークなIDを生成する関数と解説できますが、そもそもユニークユニークな値とは何でしょうか?
ユニークとは日本語に訳すと「たったひとつの」「他に存在しない」などといった意味があります。
要するに、重複しないようなIDを生成する目的で使う時にこの関数を使います。
関数自体の使い方はとても簡単ですが、この関数を使う際に少し注意しないといけない点もあります。
その注意点はいくつかありますので読み進めていただく上で書いていきます。
uniqid関数を使ってみよう
ではまず、uniqid関数を使ってみましょう。
特に難しい準備をする必要はありません。
コードをみてみましょう。
<?php echo uniqid(); ?>
実行結果:
5b4b19d3d8b95
このサンプルコードについて特に説明は必要ないかと思います。
uniqid関数を呼び出し戻り値をそのまま表示しているだけですね。
この関数では英数字を自動で生成し返してくれるという仕組みになっています。
使う上での注意点
uniqid関数の注意点ですが、この自動で生成して返してくれる仕組みは内部的に「時間」を元に生成されています。
つまり、同じマイクロ秒にこの関数が実行された場合は同じ値が戻ってきてしまうという問題があります。
例えば、for文内でuniqidを短時間に何回も呼び出す場合はこういった問題が発生する可能性があります。
そういった問題点を緩和する方法として次に、接頭辞を付けた方法について解説していきます。
<?php echo uniqid('AAA_'); ?>
実行結果:
AAA_5b4b1aea2cec4
このようにuniqid関数の引数に文字列を渡すことで生成したユニークIDの前に指定した文字列を付加することができます。
これを接頭辞といい、もし同じマイクロ秒にuniqid関数を実行したとしても別々の接頭辞をつけることができれば少し緩和できるのではないかと思います。
(接頭辞の本来の使い方がこうかと言われるとちょっと違うのですがこういう使い方もあります。)
まだまだ注意点があります。
このuniqid関数やそれとともに使うことの多い関数について次の章で注意点を見ていきましょう。
uniqid関数をパスワードといった重要な文字列として使う?
結論:そのまま使うべきではない
uniqid関数は一見するとランダムな英数字を生成して返しているのでこれをパスワードとして使いたくなる方がいるかもしれません。
しかし、これをパスワードとしてそのままデータベースに保存するなどの使い方をするのはやめましょう。
この値をパスワードの値として使いたいのなら暗号化などの処理を施して使うべきです。
他の人に推測されにくいという理由だけでそのまま値を保存するのは危険なので絶対にやめましょう。
パスワードとして使いたいなら・・・
では、どうやって暗号化するのがよいでしょうか?
古い解説書や解説サイトの場合はmd5関数やsha1関数などと併用する形で解説されていますが、現在この形は推奨されていません。
これは公式ドキュメント上でも記載されていますが、md5やsha1はブルートフォースという手法を使うことで簡単に元の文字列が判明してしまいます。
このあたりについては公式ドキュメントの「よく使われるハッシュ関数である md5() や sha1() は、なぜパスワードのハッシュに適していないのですか? 」をご覧ください。
ではどのような手法で暗号化するのがよいでしょうか?
それはpassword_hash関数やcrypt関数を使うことで実現することができます。
これらの関数の使い方は今回説明はしませんが、そこまで難しくはありません。
こういった関数を使って暗号化していきましょう。
特殊な例
この章ではuniqid関数では自分の意図する結果が得られないという方に向けた章になっています。
文字列のみで生成したい
uniqid関数では英数字両方が混ざった形の値が返されますが、英字文字列だけが良いという場合は次のような関数を作成することで実現できます。
<?php echo strGenerate(); // 引数で指定した長さ分の文字列を生成する関数 function strGenerate($length = 8) { $output = ''; $ary = range('a', 'z'); $max = count($ary); for($i = 0; $i < $length; $i++) { $output .= $ary[random_int(0, $max)]; } return $output; } ?>
実行結果:
gkypdlxg
やっていることはとても単純でrange関数を使ってアルファベットのa~zを配列として$aryで受け取っています。
あとは引数で指定されている回数分forを回し、random_int関数を用いて$outputに1文字ずつ文字を末尾にくっつけているだけです。
数字のみで生成したい
先程は文字列のみの場合でしたが、数字のみの場合はどうすればよいでしょうか?
次のコードをみてみましょう。
<?php echo numGenerate(); // 引数で指定した長さ分の文字列を生成する関数 function numGenerate($length = 8) { $output = ''; $ary = range('0', '9'); $max = count($ary); for($i = 0; $i < $length; $i++) { $output .= $ary[random_int(0, $max)]; } return $output; } ?>
実行結果:
01225280
先程のstrGenerate関数を作る例とそんなに変わらないことがわかりますよね。
これで数字だけを並べることに成功しました!
ただし、このrandom_int関数はPHP7以降しか対応していません。
そのためお使いのPHPのバージョンが古くないか注意が必要です。
まとめ
いかがでしょうか?
uniqid関数の使い方について見てきました。
特に使い方は難しくありませんが、英字のみ、数字のみとこだわりがある場合はサンプルコードにあるように、独自実装しましょう。
(そこまで難しくないですよね?)
また、ユニークIDをパスワードとして使う場合には適切な暗号化処理を施した上で使う必要があります。
このあたりは間違えないように注意する必要がありますね!
では、またどこかでお会いしましょう!