質問: 会員制の学習支援サイトをcakephp2.7で作りたいのですが、具体的にどういうテーブル設計にすればよいかよくわかりません。 まず会員制なので会員テーブル(usersテーブル)でusernameカラムとpasswordカラムを用意。 cookbookのチュートリアルにあるようにこの命名規則に従うと「ユーザーログインを 実装するにあたってほとんどのことを CalePHP が自動的に設定します」ということでチュートリアルを進めた結果確かにログイン機能はできました。 次に、問題演習のための問題文テーブル(questionsテーブル)。 カラムは問題IDカラム、q_body(問題文)カラム。 この問題文テーブルに10問(10行)データが入っているとします。 やりたいことは、会員登録したユーザ毎の進捗度の管理です。 今考えているのは、ユーザ毎に進捗度テーブルを作って管理する方法です。 進捗度テーブルには、問題IDカラム、1回目の結果を書き込むtry1カラム。2回目の結果を書き込むtry2カラム。...を用意するつもりです。 ユーザーが、初めて問題1を解いたら進捗度テーブルの問題1の行のtry1カラムに結果を書き込む。 ユーザーが、再び問題1を解いたら進捗度テーブルの問題1の行のtry2カラムに結果を書き込む。 というようなことを実現したいです。 この場合会員1人につき進捗度テーブルを一つ用意することになると思うのですが、具体的にやるとなるとどうしていいかよくわかりません。 1. 会員登録時にその人用の進捗度テーブルを作る方法。 2. 1ができない場合、あらかじめ進捗度テーブルを連番でいっぱい作っておいて、会員登録した順に会員番号と進捗度テーブルを結びつける。 と、いうことも考えたのですが、いずれにしても会員番号とその人用の進捗度テーブルを結びつける方法が必要。 つまり会員Aは会員A用進捗度テーブルには書き込めるが、他の会員用の進捗度テーブルには書き込めないような仕組みが必要。 そのためには会員Aがログインした場合A用進捗度テーブルに書き込むためのフォーム(ページ)が表示されるようにする必要がある。 これって会員制サイトのいわゆるマイページにあたるものだと思うのですが、どうすれば実現できるでしょうか? とりあえずテーブル設計の考え方は上記の方針で問題ないでしょうか(これでやりたいことが実現可能でしょうか?) 上記の方法では無理あるいは著しく非効率なので普通はこうする、みたいなのがあればお願いします。
回答: 進捗度テーブルは一つ作れば十分だと思います。私ならそうします。 進捗度テーブルに、ユーザーid(username)を格納するカラムを用意すればいいのです。 (ユーザーidは会員テーブルの主キーだと思うので、進捗度テーブルからしたら、外部キーということになります。が、外部キーはデータベースエンジンによっては、必ずしも実装されているわけでもないので、それほどこだわる点ではないかもしれません。) カラム構造としては以下の4種 ``` 年月日時分秒,ユーザーid,問題番号,結果 ``` 同じユーザーが同じ年月日時分秒で2問以上解けることは考えにくいので、年月日時分秒とユーザーidをセットにすれば、一意性のある primary key として機能します。 リレーショナル・データベースでは、クエリー(検索)時に、テーブルの写像(部分集合)を取り出すことができるので、 > > つまり会員Aは会員A用進捗度テーブルには書き込めるが、他の会員用の進捗度テーブルには書き込めないような仕組みが必要。 > > > このようなことも、一つの進捗度テーブルで実現できます。一般的に DBMS では ``` SELECT * FROM 進捗度テーブル WHERE username='ユーザー名'; ``` といったような SQL を使うなりする形になります。これにより、特定のユーザー名をもったエントリーのみの集合を結果として得ることができます。 SQL の`WHERE`句は CakePHP なら`find`メソッドで渡すパラメーターで、`conditions` を設定することに相当すると思います。 ある問題を解いた回数も、同じユーザーの同じ問題に関するエントリーがいくつあるかをクエリーで調べることで足るので、特に、Try1〜TryNまでの項目を「カラムとして用意する」必要はありません。カラムにする設計だとむしろ柔軟性に欠けます。 CakePHP 自体は特に Web の UI の部分をフレームワークとして提供してくれていますが、データベースに関する理解は前提条件として求められていると思います。suzukisさんが既にコメントで言及されているように、まずは CakePHP といった特定のフレームワーク・実装を扱う以前に、一度、リレーショナル・データベースについてせめて初級程度の勉強は別途済ませておくことをお勧めします。