例えば $tags に array(‘foo’, ‘bar’, ‘baz’) と入っていて
これらのタグがデータベースへ未登録の場合に
INSERT するという作業を行いたいときは
Tag モデル内で
foreach ($tags as $tag) { if (!$this->findByTag($tag)) { $data['Tag']['tag'] = $tag; $this->save($data); } }
こんな感じでよさそうなものだが、
これだと2周目以降がUPDATEになってしまう。
INSERT INTO `tags` (`tag`,`modified`,`created`) VALUES ('foo','2008-02-28 14:45:50','2008-02-28 14:45:50') UPDATE `tags` AS `Tag` SET `Tag`.`tag` = 'baa', `Tag`.`modified` = '2008-02-28 14:45:50' WHERE `Tag`.`id` IN (1) UPDATE `tags` AS `Tag` SET `Tag`.`tag` = 'baz', `Tag`.`modified` = '2008-02-28 14:45:50' WHERE `Tag`.`id` IN (1)
3周分のデータを確認しても
Array ( [Tag] => Array ( [tag] => foo ) ) Array ( [Tag] => Array ( [tag] => baa ) ) Array ( [Tag] => Array ( [tag] => baz ) )
別に id は指定されていないのだが、
どうもうまくいかない。
というわけで id を無理矢理 null にしてみた。
foreach ($tags as $tag) { if (!$this->findByTag($tag)) { $data['Tag'] = array( 'id' => null, 'tag' => $tag, ); $this->save($this->data); } }
これで成功。
何だかあまりスマートじゃない気がするけど、
動かないよりはマシなのでこれで。
きっともっと賢い方法があると思うので
あとはいつもの他力本願。誰かよろしく!
追記
その後、よりそれらしい方法を教えていただいた。
@kosugi と、コメントをくれた方、ありがとうございます。
Model::create() でよかった。
cake/libs/model/model.phpの
create メソッドのコメントによると
Initializes the model for writing a new record, loading the default values for those fields that are not defined in $data.
($data で定義されていないフィールドにデフォルト値を読み込んで、新しいレコードを書き込めるようにモデルを初期化します。)
とのこと。
これで Model の状態がリセットされるので、
初回と同じく INSERT されるようになる。
というわけで、先ほどの処理はこんな感じかな?
foreach ($tags as $tag) { if (!$this->findByTag($tag)) { $this->create(); $data['Tag']['tag'] = $tag; $this->save($data); } }
$this->create();
は
$this->save($this->data);
の前でも後でも結局は同じ結果だと思うが、
初期化するという意味では前の方が自然な気がする。
2008/02/28 19:25
私もはまりました
↓のようにcrate()でモデルを初期化するといいみたいです
$this->Tag->create();
$this->Tag->save($tagData);