質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

13356閲覧

PHP 数字のみのユニークなIDを生成する方法

keita0236

総合スコア25

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

1クリップ

投稿2017/01/28 16:04

こんばんは。
最近PHPを本格的に勉強し始めました。
標題ですが、PHPで下記の条件を満たした
ユニークなIDを生成したいと思っておりますが
その方法がわからず困っております。
ウェブで調べるとユニークidの生成には、uniqid()などがありましたが、これだと半角英字が含まれて生成されるため、下記の条件を満たしません。
つきましては、下記の前提および条件を満たすPHPでのユニークidの生成方法を教えて頂けないでしょうか。
お手数ですが、よろしくお願いします。

※重複については、PHP側でのメソッドがなければ、最悪DBへの登録時にユーザーのidカラムと照合させて対応させます

<前提・用途>
①ウェブサービス上でユーザーそれぞれに対して付与する固有の値(ユーザーID)として利用
②そのため、重複はなくす形にする
③プロフィール設定画面などでユーザーにも見えるデータである

<条件>
①重複はなく、それぞれがユニーク
②形式としては半角数字のみとし、半角英字は含まない(FacebookのユーザーIDのイメージです)
③ケタ数は、10桁を想定
④11111111のようなID内の数字の重複をなるべくなくす

退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

通し番号などを使わずにこの方法を取るのは、とてもおもしろいですね。良いと思います。

それで問題の部分ですが、たぶんランダムな数が欲しいのならば、uuidではおっしゃるとおり数字以外の文字が含まれてしまうので、ランダムな数字を発生させる関数を使うのはどうでしょうか。

random_int()等なら、数学的にも安全(らしい)です。
http://php.net/manual/ja/function.random-int.php

あとは、これだと数字の範囲しかしていできないので、少し高度ですがこちらはどうでしょう。
http://php.net/manual/ja/function.openssl-random-pseudo-bytes.php

openssl_random_pseudo_bytes(4)みたいに引数にバイト数を入れると、その大きさのランダムなバイナリを返してくれます。このままじゃ数字じゃないので、一旦bin2hexで16進数にして、hexdocで10進数にしてみたりだとか。

hexdec(bin2hex(openssl_random_pseudo_bytes(4)));
こんなかんじとか。

でもそこまで理由がないのならば、できるだけUUIDを使うことをおすすめしますよー。

投稿2017/01/28 16:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keita0236

2017/01/28 17:01

いろいろとご丁寧にありがとうございます! なるほど、乱数で数字を生成させる方法がいくつかあるのですね。ただ、まだPHPのスキルが低いためあまり高度な関数を使うと後からメンテナンスが厳しくなるため、ご記載の通りUUIDか通し番号を採用したいと思います。 その上で、uniqId()だと英字が含まれてしまうため、mysql側でauto_incrementを使用して通し番号を割り振って行く形を想定しております。 その際に疑問なのですが、ユーザーIDは10桁の数字の羅列の形式を取るとした場合に、例えば1人目のユーザーのIDを0000000001, 2人目を000000002となるわけですが、mysql側でのauto_incrementはどのように指定すればよろしいでしょうか。 (DBはmysqlを使用しています) auto_incrementは1,2,3,4という形で先頭に0がついていたらNGな印象があります。 なお、先頭に0の羅列をつけているのは、全ユーザーでIDのケタ数(length)を同一にしたいためです。 長々と申し訳ありませんが、お答えいただけると幸いです。
退会済みユーザー

退会済みユーザー

2017/01/29 08:36 編集

auto_incrementを使ったことがないので丸投げですみません。 調べてみたらこんなサイト様が出てきました。 http://d.hatena.ne.jp/minmin_lucky7/20110428/p1 どうやら、カラムにautoincrementを指定するときにzerofillも指定してあげればいいようです。 (auto_incrementなんて便利なものが会ったのですね〜僕は全部最大のidを読みだしてそれに1を足すというやり方をしていました笑 こちらこそ勉強になりました。ありがとうございました!頑張ってくださいね。)
keita0236

2017/01/30 01:29

度々ありがとうございます! zerofillなんてものがあったとは、知りませんでした。難しいことはせず、auto_incrementとzerofillでとりあえず対応出来そうです。 ありがとうございました!
guest

0

連番やタイムスタンプなど規則正しく取らずに、ランダムに付けていった場合、誕生日攻撃と呼ばれるように、案外早く衝突してしまいます。

10進法10桁だと、衝突を無視できるのはその平方根の、ざっと10万件ぐらいになります。

投稿2017/01/28 22:28

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keita0236

2017/01/29 01:30

コメントありがとうございます! なるほど、そういった側面の考えが浅かったです。やはり連番形式がベターなのですね。 なお、連番をつける上で10桁で統一し、0000000001, 0000000002という形でauto_incrementを行いたいのですが、これはPHP側で制御できるのでしょうか?mysqlのカラムでauto_increment値を設定してあげればいいのですが、auto_incrementは1,2,3という形で増加するため、今回の要件のように頭に0が羅列されている形式だとエラーになるかと危惧しています。 また、000000009から次に増える際(桁が繰り上がる際)に0000000010となりますが、その際に0を1つ省いて〜といった処理もsqlでは制御できないのではないかと。 お手数ですが、上記実装するために最適な方法がありましたら、お知らせ頂ければ幸いです。
maisumakun

2017/01/29 03:07

てっとり早いのは、PHP側でsprintf('%010d', $val)のようにして表示桁数を固定してしまうことだと思います。
guest

0

連番orタイムスタンプで良いかと。

投稿2017/01/28 16:10

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keita0236

2017/01/28 17:02

お答えいただきありがとうございます! タイムスタンプ形式は初耳でした、ありがとうございます。また、やはり連番形式がセオリーなのですね、勉強になりました。
退会済みユーザー

退会済みユーザー

2017/01/29 01:42

DB で扱う id と 入力 id の差は、入力 id を文字列として扱い桁数チェックを行い、DB との比較を行う時 int 型にキャストして比較やれば良いです。 分からなければ、質問を分けて新しく質問し直したほうが良いです。 unique id に関しては私も質問しているのですが、連番、タイムスタンプを基準とする以外は、桁数を増やす対応ぐらいしか思いつかないですね。。。 https://teratail.com/questions/62553
keita0236

2017/01/30 01:31

確かにちょっと質問がPHPから逸れていましたね、失礼しました。 様々な方法があるようですが、とりあえずonokatioさんがコメントされたauto_incrementとzerofillの組み合わせが現状良さそうなので、こちらをBAにさせていただきました。te2jiさんもお忙しい中コメント頂きありがとうございました!
退会済みユーザー

退会済みユーザー

2017/01/30 02:03 編集

DB上に連番を作る方法は、様々な方法はありません。 普通は AUTO_INCREMENT 一択です。 MySQLであれば、使用方法に関して、マニュアルに記載があります。 https://dev.mysql.com/doc/refman/5.6/ja/example-auto-increment.html 基本動作に関して、マニュアル以上に信頼できる情報はないので、まずはマニュアルをあたるようにして下さい。 私と maisumakun さんが追記しているのはその先の話です。 懸念されているとおり、桁数まで含めてユーザーIDとして扱うのであれば、入力データは文字列として扱う必要があります。 DB上のデータとの比較は、型変換が必要であり、maisumakun さんは入力データには手を加えず、DBデータを突合の際、桁数補完するのが手っ取り早いとアドバイスしてくれており、私は逆に、入力データが必要な桁数を持っていることとを確認した後、DBデータに型を合わせて突合すれば良いと言っています。完全に PHP での処理の話です。 不明であれば、改めて質問し直して下さい。理由は内容が「ユニークなIDを生成」から大きく外れるからです。 あと、蛇足ですが、「zerofill」の記事、使用するならちゃんと読んだほうがイイですよ。 --- //直書きで取得してみる $sql = "SELECT id FROM table1 WHERE id = 000000000001"; echo $row['id']; //000000000001 平気! //0で埋めないでやってみる $sql = "SELECT id FROM table1 WHERE id = 2"; echo $row['id']; //000000000002 これでも平気! ---
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問