例えばお問い合わせフォームとかで、名前とメアドは必須とする。ただ、あるユーザーはドロップダウンで予算種別や流入経路を出したい、とあるユーザーはFAX番号も出したい、みたいなやつ。
スキーマレスのFirebaseの場合ユーザーごとにスキーマ作れば終わる(アプリ側は大変だけど)んだけど、RDBはそうもいかないよね。
今まで見たなかで大きく3パターンあるようなので、整理をする。
1. 属性ごとにテーブルが作成する
DrupalというCMSで見たパターン。
属性を追加することでconfigが更新され、configには追加したフィールドの格納場所がわかる。で、Field API
でカスタム属性をを全部引っ張ることができるようだ。
2. metaテーブルを作る
WordPressが得意としている実装。option_meta
とかuser_meta
とか。
field_name
とfield_value
を保存するテーブルを作って、キー/値ペアを作るやつです。カラムのスキーマはバイナリ以外は自動的に文字列になるので、そのあたりが微妙。重量みたいなカスタム属性があって、4.3kgである場合、本来はDecimal(10,1)とかなんだろうけど。型情報も保存して、toXXXいれるしか無いんかな?
この種の設計は、SQLアンチパターンとはされているけど、格納する→表示するだけなら、まぁそこまで。検索したいとなると、無理。格納表示ならJSONでよいだろって思い始めている。
EAVだと検索性が死ぬので、それらの対応策としては、親のテーブルにtype属性を作って、そのtype属性に応じたテーブルを作りJOINするパターンが有る。STIってやつですかね。単一テーブル継承。
マルチテナントのアプリケーションになっちゃうと、ユーザー単位でSTIが作られるので、テーブルの継承が出ずに、結局EAVにならざるをえない(型が決まらないので)。field_type
field_name
field_value
validation
みたいなテーブル作って、そこで頑張る感じかな。。。
3. JSONカラムを作って逃げる
WordPressのカスタムプラグインなんかで、どっかで見た実装。フィールド、ラベル、タイプ、バリデーションなどをJSONで用意して、動的にフォームを組み立てて、値も入れちゃうパターン。実装も単純。