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

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

ただいまの
回答率

90.52%

  • PHP

    20288questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 2,377

keita0236

score 17

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

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

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

それで問題の部分ですが、たぶんランダムな数が欲しいのならば、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/29 02: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 17:35 編集

    auto_incrementを使ったことがないので丸投げですみません。
    調べてみたらこんなサイト様が出てきました。

    http://d.hatena.ne.jp/minmin_lucky7/20110428/p1

    どうやら、カラムにautoincrementを指定するときにzerofillも指定してあげればいいようです。


    (auto_incrementなんて便利なものが会ったのですね〜僕は全部最大のidを読みだしてそれに1を足すというやり方をしていました笑
    こちらこそ勉強になりました。ありがとうございました!頑張ってくださいね。)

    キャンセル

  • 2017/01/30 10:29

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/29 02:02

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

    キャンセル

  • 2017/01/29 10:42

    DB で扱う id と 入力 id の差は、入力 id を文字列として扱い桁数チェックを行い、DB との比較を行う時 int 型にキャストして比較やれば良いです。
    分からなければ、質問を分けて新しく質問し直したほうが良いです。

    unique id に関しては私も質問しているのですが、連番、タイムスタンプを基準とする以外は、桁数を増やす対応ぐらいしか思いつかないですね。。。

    https://teratail.com/questions/62553

    キャンセル

  • 2017/01/30 10:31

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

    キャンセル

  • 2017/01/30 10:51 編集

    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 これでも平気!
    ---

    キャンセル

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/29 10:30

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

    キャンセル

  • 2017/01/29 12:07

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

    キャンセル

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

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20288questions

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