例えば $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);