データベース
記事のデータを入れる「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に設定します。
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 ), );}class Tag extends AppModel { public $name = 'Tag';}class PostsTag extends AppModel { public $name = 'PostsTag';}Controler
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
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」を入れます。
データ更新(アップデータ)
次にすでに登録してあるデータの更新(アップデータ)です。
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); }}コントローラーは特に特別なことないですね。
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モデルに以下を追加します。
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;}コントローラーです。
何もしなかったらチェックボックのエラーが表示できなかったので、わざわざメッセージを取得しています。
$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のチェックボックの取得したエラーメッセージをチェックボックスの下に表示させています。
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つも選択されてなかったときにエラー表示されます。
もっと上手いやり方があると思いますが僕のスキルではこの程度でした。


