各タスクに対してメモもつけられたら便利ですよね。
tasksテーブルでメモを管理しても良いのですが、今回はnotesというテーブルを新しく作成し、アソシエーションによって2つのモデルを関連付けましょう。
モデルは基本的に独立して動きますが、アソシエーションを効かせることで、Taskモデルから値を取得するとき、一緒にNoteモデルからも値を引っ張ってくるようになります。
notesテーブルの作成
下記のSQL文により、notesテーブルを作成しましょう。
CREATE TABLE `notes` ( `id` INT NOT NULL AUTO_INCREMENT, `task_id` INT NOT NULL, `body` TINYTEXT NOT NULL, `created` DATETIME NOT NULL, `modified` DATETIME NOT NULL, PRIMARY KEY (`id`)) ;
Noteモデルの作成
次にnotesテーブルに対応するNote.phpを作成します。
$belongsToがアソシエーションに必要なプロパティですが、これは後ほど説明します。
<?php // app/Model/Note.php class Note extends AppModel { public $belongsTo = array('Task'); }
Notesコントローラーの作成
NotesController.phpです。
面倒なので、$scaffoldを使ってしまいましょう。
<?php // app/Controller/NotesController.php class NotesController extends AppController { public $scaffold; }
ここまで実装した上で、http://192.168.33.10/cakephp-tasks/Notes/createにアクセスしてみると、$scaffoldによって生成されたページが表示されます。
Taskという項目で、すでに登録したタスクが選択できるのが分かるでしょうか?
これはアソシエーションにより、NoteモデルがTaskモデルに紐付いていると定義されたからです。
ただし、このままだとNoteモデルからTaskモデルへの片思いなので、Taskの方も修正します。
Taskモデルの修正
<?php// app/Model/Task.php class Task extends AppModel { public $hasMany = array('Note'); // ここから下は前項のバリデーションなので省略 }
ここで出てきた$hasManyと先程の$belongsToがアソシエーションのキモです。
$hasManyと$belongsToをざっくり説明すると以下のようになります。
$hasMany => このモデルはいくつかのモデルを従えている(上位モデル)
$belongsTo => このモデルは上位モデルの下についている(下位モデル)
Task.phpは$hasMany、Note.phpは$belongsToでお互いを指定しているので、
上位モデル => Task
下位モデル => Note
となります。
つまり、どういう動きするんだってばよ?
ということで、続いてビューも修正していきます。
一覧ページの修正
<!-- app/View/Tasks/index.ctp --><!-- 省略 --> <table> <tr> <th>ID</th> <th>名前</th> <th>期限日</th> <th>作成日</th> <th>操作</th> </tr> <?php foreach($tasks_data as $row): ?> <tr> <td><?php echo $this->Html->link($row['Task']['id'], '/Tasks/view/' . $row['Task']['id']); ?></td> <td><?php echo h($row['Task']['name']); ?><br /> <ul> <?php foreach($row['Note'] as $note): ?> <!-- Noteモデルのデータを表示 --> <li><?php echo h($note['body']); ?></li> <?php endforeach; ?> </ul> </td> <td><?php echo h($row['Task']['due_date']); ?></td> <td><?php echo h($row['Task']['created']); ?></td> <td><?php echo $this->Html->link('このタスクを完了する', '/Tasks/done/' . $row['Task']['id']); ?></td> </tr> <?php endforeach; ?> </table> <!-- 省略 -->
コントローラーは変えておりませんが、アソシエーションを組むことで、Taskモデルから値を取得する際にNoteモデルからも値を取得してきます。
そのため、同じ$task_dataでありますが、tasksテーブルの値とnotesテーブルの値を含んでおります。
後は、トリガーにモデル名を指定してあげれば、そのモデルの値を引っ張ってきます。($row[‘Task’]、$row[‘Note’])
それではアクセスしてみてください。
え、何も変わらないって?
そうですね。まだnotesテーブルに何も値を入れていませんでした。
下記のアドレスにアクセスし、notesテーブルに新規登録しましょう。
http://192.168.33.10/cakephp-tasks/Notes/create
このとき、Taskの項目を選択すると、あなたがすでにtasksデータに登録した値が表示されます。
これもアソシエーションのおかげです。
それでは好きなタスクに好きなメモを残しましょう。
メモを登録したら、http://192.168.33.10/cakephp-tasks/Tasks/indexに戻りましょう。
メモが登録されていますね。
余談ですが、画面下部に出ているのが、このページにてモデルが実行した処理です。
ちゃんとtasksテーブルとnotesテーブルの両方から取得していることが分かります。