状況
Laravel:6.2
DB:MySQL
会員制SNS風サイトの開発。
当初はuserテーブルとarticleテーブルの主キーを連番のidにしていたが
ユーザーや記事の個別ページのURLにidを使用するにあたり
主キーをUUIDに変更しようと思った。
("example.com/user/3"みたいな感じで少ない会員数がurlの数字でバレるのに抵抗があった)
以下、かなり個人的な判断や事情が含まれるため参考になるか不明ですが
自分用のメモも兼ねて書かせて頂いています。
やってみたこと
カラム型を変更しようとした
まず、テーブルに入ってるデータ消したくなかったので、
ロールバックはせずにカラム型変更用のマイグレーションファイルを作成して対応しようと思った。
カラム型を変更するには
doctrine/dbalというライブラリのインストールが必要らしい。
Laravel 6.* ではdoctrine/dbalの対応バージョンが3.* ではなく2.* らしいので
バージョン指定してインストールする
それとUUIDを使うのにもパッケージをインストールしなければならないので下記コマンド実行
composer require goldspecdigital/laravel-eloquent-uuid:^6.2
(バージョンはlalavelのバージョンに合わせて適宜変更する)
各インストールが終わったのでマイグレーションファイル作成して
$table->uuid('id')->primary()->change();
などとしてマイグレーションを実行するもエラー。
調べてみると、UUIDはchangeには対応してない様子。
カラム型変更はあきらめる。
テーブルを作り直そうとした
上記の通りカラム型変更では対応できなかったので
テーブルのデータを消して改めてmigrateしようと思った。
ロールバック後にマイグレーションファイルのuserテーブルとarticleテーブルを
$table->bigIncrements('id');
から
$table->uuid('id')->primary();
に変更してmigrateしてみた。しかしエラーが出た。
原因として、今回uuidにしようとしたuserテーブルのidは、articleテーブルのほうで
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
といった感じで関連付けされてるので、articleテーブルのuser_idカラムを
userテーブルのidと同じ形式(つまりUUID)にしなければいけないらしい。
ここで今更ながら、「本当にUUIDを使わなければならないのか?」と疑問に思う。
UUIDの使用をやめた理由
改めて考えてみた結果、
uuidは長すぎる
5e4e81de-45ae-468b-b33c-4c6109ded561(こんな感じになる)
ので、urlに使うには不格好なのではないかと感じ始める。
また、
「ちなみにUUIDをプライマリキーにする人もいますが、
外部キーとして使用することもある場合は、別にUUID用のカラムを作った方が良きです。
リレーれション先でも128ビットの数値をデータとして持っておくのは非効率ですからね。」
という意見も目にし、主キーにUUIDを使用するのはやめることにする。
参考にさせて頂いた記事
https://qiita.com/howaito01/items/b529af6f4d3112b91818)
最終的な対応
主キーとは別にurl表示用のランダム値(に見える)のカラムを作ることにした。
そもそも
連番にしたくなかった理由は
「urlを連番の数字にすると、会員数や投稿数が簡単にわかってしまうから」
だったので
「idに9999をかけて16進数に変換した値」等でも充分だと思った。
一見では規則性はわからないし、idを元にしているので重複することもないため。
処理としては、
userなりarticleなりの新しいレコードを登録してからでないと、そのレコードのIDがわからないので
下記のような感じで、一度saveしてからdisplay_id(url表示用のランダム風id)を設定し、もう一度save。
$article->title = $request->title;
$article->user_id = $request->user()->id;
article->save();
$article->display_id = "a-".dechex($article->id * 9999);
$article->save();
//dechexは10進数を16進数に変換する関数