【CakePHP】アソシエーションのモデルにも一緒に保存する際の注意点

CakePHP 1.3.2】

【状況】
主:Userモデル->従:Profileモデル、という関係。

【失敗】
下記では、必ず新規作成(INSERT)となってしまい、既存のデータの
変更(UPDATE)ができません。

【/app/controllers/users_controller.php
//フォーム送信後の処理。データベースに保存。
if(!empty($this->data)){
$this->User->saveAll($this->data);
}


【成功】
そこで、従属モデルProfileのidフィールドを、保存するデータに含めます。
これで、すでにレコードが存在する場合はUPDATEとなります。

【/app/controllers/users_controller.php
if(!empty($this->data)){
$profile = $this->User->Profile->find('first', array(
'conditions'=>array('user_id'=>$this->data['User']['id'])
));
$this->data['Profile']['id'] = $profile['Profile']['id'];

$this->User->saveAll($this->data);
}


【saveAllを2回に分けて】
しかし、さらに問題があります。
現在のところ、saveAllを使った場合、バリデーションに失敗した場合は
コミットもロールバックもされず、トランザクションが開始された
状態のままになるそうです。


CakePHP 1.3でのトランザクション処理の方法と注意点 - (DxD)∞


ですから、上の記事のおすすめの通り、saveAllをバリデーションと
保存とに二つに分けて行うのがいいと思います。


【/app/controllers/users_controller.php
if(!empty($this->data)){
//Userモデルで保存
if($this->User->saveAll($this->data, array('validate' => 'only'))) {

$profile = $this->User->Profile->find('first', array(
'conditions'=>array('user_id'=>$this->User->id)
));
$this->data['Profile']['id'] = $profile['Profile']['id'];
$this->User->saveAll($this->data, array('validate' => false));
}
}