データベース
記事のデータを入れる「Posts」、タグ(カテゴリー)データを入れる「Tags」、関連付け用の「PostsTags」があります。
Posts
id | bigint(20) |
---|---|
name | varchar(100) |
Tags
id | bigint(20) |
---|---|
name | varchar(100) |
PostsTags
post_id | bigint(20) |
---|---|
tag_id | varchar(100) |
最低限こんなとこでしょうか。
Model
hasAndBelongsToMany(HABTM)はpostに設定します。
models > post.php
- class Post extends AppModel {
- public $name = 'Post';
- public $hasAndBelongsToMany = array(
- 'Tag' => array(
- 'className' => 'Tag',
- 'joinTable' => 'posts_tags',
- 'foreignKey' => 'post_id',
- 'associationForeignKey' => 'tag_id',
- 'fields' => array('id','name'),
- 'unique' => true
- ),
- );
- }
models > tag.php
- class Tag extends AppModel {
- public $name = 'Tag';
- }
models > posts_tag.php
- class PostsTag extends AppModel {
- public $name = 'PostsTag';
- }
Controler
controllers > posts_controller.php
- class PostsController extends AppController {
- public $name = "posts";
- public $uses = array("Post", "Tag", "PostsTag");
- /* レコードの追加
- ============================================== */
- function add() {
- if (!empty($this->data)) {
- $this->Post->save($this->data);
- }
- //Tagデータを渡す
- $tagData = $this->Tag->find('list');
- $this->set('tagData', $tagData);
- }
- }
チェックボックで配列になってるからうーん、、、とか深く考えないで「save($this->data)」だけでCakePHPが勝手に処理してくれるっぽいです。
View
views > posts > add.php
- echo $form->create('Post', array('type' => 'post'));
- echo $form->input('Tag', array(
- 'type'=>'select',
- 'multiple' => 'checkbox',
- 'options' => $tagData,
- 'label' => 'タグ));
- echo $form->end('投稿');
フォームヘルパーにはチェックボックス用の「$form->checkbox」もありますが、配列から一気に作りたいときは「$form->input」を使います。
「options」にコントローラーから受け取った「tagData」を入れます。
データ更新(アップデータ)
次にすでに登録してあるデータの更新(アップデータ)です。
controllers > posts_controller.php
- function admin_update($id = null) {
- $this->Post->id = $id;
- if (empty($this->data)) {
- $this->data = $this->Post->read();
- $this->set('result', $this->data);
- //Tagを渡す
- $tagData = $this->Tag->find('list');
- $this->set('tagData', $tagData);
- }
- elseif (!empty($this->data)) {
- $this->Post->save($this->data);
- }
- }
コントローラーは特に特別なことないですね。
views > posts > update.php
- echo $form->create(null, array('type' => 'post', 'action' => './update'));
- echo $form->input('Tag', array(
- 'type'=>'select',
- 'multiple' => 'checkbox',
- 'options' => $tagData,
- 'label' => 'タグ'));
- echo $form->end('投稿');
ビューはPostsTagsで関連してるところはselectedでチェックして、、、とか深く考える必要ありませんでした。
新規追加(add.php)と同じで、関連付けされているタグには勝手にチェックされて表示してくれます。
チェックボックスのバリデーション
最後にチェックボックスのバリデーションを行います。
postモデルに以下を追加します。
models > post.php
- public $validate = array(
- 'Tag' => array(
- 'multiple' => array(
- //'rule' => array('multiple',array('min' => 1, 'max' => 2)),
- 'rule' => array('multiple',array('min' => 1)),
- 'message' => '1つ以上選択してください。'
- ),
- )
- );
- function beforeValidate() {
- foreach($this->hasAndBelongsToMany as $k=>$v) {
- if(isset($this->data[$k][$k])) {
- $this->data[$this->alias][$k] = $this->data[$k][$k];
- }
- }
- return true;
- }
引用元:HABTM form validation in CakePHP
コントローラーです。
何もしなかったらチェックボックのエラーが表示できなかったので、わざわざメッセージを取得しています。
controllers > posts_controller.php
- $this->Post->save($this->data);
- if ($this->Post->validates()) {
- $this->redirect('/posts/');
- } else {
- $this->set('result', $this->data["Post"]);
- //エラーメッセージを取得
- $errors = $this->Post->invalidFields();
- if(!empty ($errors['Tag'])) {
- $this->set('tagerror', $errors['Tag']);
- }
- }
- }
Viewのチェックボックの取得したエラーメッセージをチェックボックスの下に表示させています。
views > posts > add.php
- echo $form->input('Tag', array('type'=>'select','multiple' => 'checkbox', 'options' => $tagData,'label' => 'カテゴリー'));
- //タグエラーがあったら表示
- if(!empty ($tagerror)) {
- echo '<div class="error-message">';
- print_r($tagerror);
- echo '</div>';
- }
これで一応1つも選択されてなかったときにエラー表示されます。
もっと上手いやり方があると思いますが僕のスキルではこの程度でした。