edo1z blog

プログラミングなどに関するブログです

cakePHP アソシエーションの一括save

アソシエーション: モデル同士を繋ぐ参考

PostモデルとTagモデルがhasAndBelongsToManyの関係にあるとき、Postを登録する際に、$this->request->dataが、下記にようになっていれば一括登録できるようだ。

$this->request->data = array(
    'Post' => array(
        'title' => 'タイトル',
        'content' => '内容',
        'user_id' => 1
    ),
    'Tag' => array(
        'Tag' => array(
            '0' => 1
        )
    )
);

Tagの1というのはtag_idです。 Viewでは、下記のように書けばいいようだ。

<?php echo $this->Form->create('Post'); ?>
    <?php
        echo $this->Form->input('title');
        echo $this->Form->input('content');
        echo $this->Form->input('user_id');
        echo $this->Form->input('Tag');
    ?>
<?php echo $this->Form->end(__('Submit')); ?>

コントローラはこれだけで、HABTMのアソシエーションも一括登録してくれる。

public function add() {
    if ($this->request->is('post')) {
        $this->Post->create();
        if ($this->Post->save($this->request->data)) {
            $this->Session->setFlash(__('The post has been saved'));
            $this->redirect(array('action' => 'index'));
        } else {
            $this->Session->setFlash(__('The post could not be saved. Please, try again.'));
        }
    }
    $users = $this->Post->User->find('list');
    $tags = $this->Post->Tag->find('list');
    $this->set(compact('users', 'tags'));
}

削除に関しても、Postを削除するときに、$this->Post->delete()とやるだけで、posts_tagsを一括削除してくれる。 もちろん、これらはModelのアソシエーション設定をしっかりしておくことが前提になる。

追加の一括登録時に、デフォルトではposts_tagsはユニークになるようになっていて、既にデータがある場合は削除してから、新たに追加するようだ。よって、もしposts_tagsなどの中間テーブルに各id以外の情報を登録している場合は、新たに追加する際に削除されてしまう。これを防ぐには、アソシエーション設定のuniqueに、trueではなく、keepExistingという文字列をセットする。これによって関連情報が削除されなくなるようだ。

ちなみに、Tag.idなのに、なんでTag.Tagなんだろうか?このTagは、アソシエーション設定の際のエイリアス名なんだけど、エイリアス名.エイリアス名にするのがルールなのかな??ViewのTagを、Tag.idにすると登録できなかった。TagをTag.Tagにすると登録できた。エイリアス名をTakoにして、TagをTakoにすると登録できて、TagをTako.Tagにすると登録できなかった。これからはおとなしく、viewではエイリアス名のみでいきます。