データベース
記事のデータを入れる「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つも選択されてなかったときにエラー表示されます。
もっと上手いやり方があると思いますが僕のスキルではこの程度でした。
