CakePHP

Cake2.1でフォームリストの生成(実践編その7)

更新日:

今日はフォーム内でデータベースからリストを引っ張ってきて、セレクト用のラベルを作成する方法を勉強してみたいと思います。

1. まず、『CakePHP2.1でデータの新規作成』で作成した種別分けのためのテーブル『col_assorts』を使いますので、とりあえずphpMyAdminで直接データをいくつか入力します。

2. 次にメインのテーブルである『collections』と『col_assorts』テーブルを紐づけたいと思います。

アソシエーション

3. CakePHPでは、モデル同士の関連づけをするための仕組みとしてアソシエーションという大変便利な機能があります。通常テータベースを扱う場合、異なるテーブルから同時にデータを抽出する場合はJOINを用いますが、データが複雑に絡み合ってくると、SQLの記述が困難になります。アソシエーションは、モデル内にあらかじめ関連するモデルの指定をしておくことで、必要なフィールドの名前を列挙するだけで、簡単に値が入手できたり、データを保存したりすることが出来るCakePHPならではの便利な機能です。

  • hasOne
    1対1の関係です。Aモデルの1つの行にBモデルの行が1つだけ結びつきます。関連づけを示す外部キーはBテーブル内にあります。
  • hasMany
    1 対複数の関係です。Aモデルのひとつの行にBモデルの行が複数行結びつきます。関連づけを示す外部キーはBテーブル内にあります。
  • belongsTo
    hasManyと同じく1対複数の関係です。関連づけを示す外部キーは、hasOneやhasManyとは反対で、Aテーブル内にあります。
  • hasAndBelongsToMany(HABTM)
    hasAndBelongsToManyは、他の3つのアソシエーションと比べて考え方が難しいかもしれませんが、要するに『複数対複数』の関係を表すための仕組みです。他のアソシエーションとのおおきな違いは、AテーブルにもBテーブルにも外部キーがない点です。ではどこに外部キーをおくかというと『As_Bs』という別のテーブルを作り、その中にAテーブルとBテーブルの両方を指し示す外部キーを保存することで複数対複数の関連づけを行います。

4. それでは今回はbelongsToでアソシエーションを作成します。命名規則に則ってデータベーステーブルを作成していれば、モデル内に下記のコードを追加するだけでアソシエーションの設定は完了です。

app/Model/Collection.php

//belongsToアソシエーションの設定
 public $belongsTo = 'ColAssort';

5. ブラウザで確認してみると、エラーが表示されました。どうやら命名規則が間違っているみたいです。

5. collectionsテーブルのassort_idをcol_assort_id名に変更すれば、正常に戻りました。

6. それでは、実際に『col_assorts』テーブルから種別(as_name)フィールドをFormのセレクトラベルとして表示させてみましょう。コントローラのaddアクションを下記のように修正します。

app/Controller/CollectionController.php

public function add(){
 //リクエストがPOSTの場合
 if ($this->request->is('post')) {
 //データが保存されたら
 if ($this->Collection->save($this->request->data)) {
 $this->Session->setFlash('データを保存しました');
 //indexページへ移動
 $this->redirect(array('action' => 'index'));
 //データが保存できなかったら
 } else {
 $this->Session->setFlash('Collectionテーブルは保存できませんでした。再度入力して下さい。');
 }
 }
 //col_assortsテーブルから種別テーブルリストを取得する
 $this->set('list',$this->Collection->ColAssort->find('list',array('fields'=>array('id','as_name'))));
 }

7. 次に入力フォームのadd.ctpを下記のように修正します。

app/View/Collection/add.ctp

<h1>新規入力</h1>
 <?php
 //フォームの開始を宣言する
 echo $this->Form->create('Collection');
 //入力フォームの生成
 echo $this->Form->input('title');
 echo $this->Form->input('col_assort_id',array('type'=>'select','options'=>$list));
 echo $this->Form->input('save_space');
 echo $this->Form->input('created');
 echo $this->Form->input('col_code');
 //フォームの終了宣言
 echo $this->Form->end('送信');
 ?>

8. ブラウザで確認してみます。テーブル『col_assorts』からセレクトフォームに種別データの一覧を表示しています。

9. 登録したデータを表示するためにindex.ctpを下記のように修正します。

app/View/Collection/index.ctp

<h1>私のコレクション</h1>
 <div class="paging">
 <?php
 echo $this->Paginator->prev('<<', array(), null, array('class' => 'prev disabled'));
 echo $this->Paginator->numbers(array('separator' => ''));
 echo $this->Paginator->next('>>', array(), null, array('class' => 'next disabled'));
 ?>
 </div>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <th><?php echo $this->Paginator->sort('id','ID');?></th>
 <th><?php echo $this->Paginator->sort('title','タイトル');?></th>
 <th><?php echo $this->Paginator->sort('col_assort_id','種別');?></th>
 <th><?php echo $this->Paginator->sort('created','作成日');?></th>
 <th><?php echo "コード番号";?></th>
 <th><?php echo "保管場所";?></th>
 </tr>
 <?php
 foreach ($Collections as $row): ?>
 <tr>
 <td><?php echo h($row['Collection']['id']); ?>&nbsp;</td>
 <td><?php echo $this->Html->link($row['Collection']['title'],array('action'=>'edit',h($row['Collection']['id'])),array(),'『'.h($row['Collection']['title']).'』 の編集ページへ移動します');?>&nbsp;</td>
 <td><?php echo h($row['ColAssort']['as_name']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['created']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['col_code']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['save_space']); ?>&nbsp;</td>
 </tr>
 <?php endforeach; ?>
 </table>

10. ブラウザで確認してみます。きちんと登録できました。余談ですが、先日、娘が映画『テルマエ・ロマエ』を見に行きたいというので、家族で見に行きました。久しぶりに楽しめる映画でした。お奨めですよ。

11. 種別は邦画になっていますが、データテーブル(collections)には、数字2が登録されています。

本日は以上です。

-CakePHP
-

Copyright© WinRoad徒然草 , 2018 All Rights Reserved Powered by AFFINGER5.