シェアする

  • このエントリーをはてなブックマークに追加

[CakePHP]1.2.0.7962のModel::deleteについて

概要

いやー焦った。ほんとに焦った。
今日出社したらCakePHPで作った社内システムのデータが一部消えてたんですよ*[1]
考えられる原因はただ一つ。昨日みんなの仕事が終わった後に*[2] CakeをRC4からstableに更新したのが原因だと思われます。

もしかしたら他にもこんな状況に陥る人がいるかもしれないからここにメモしておきますね。
あ?俺もなった?って人がいたらコメントくれると嬉しいです。

追記:原因が判明しました!
アソシエーションのconditionsを「array(“フィールド”=> “値”)」と書かなくてはならないところ「”フィールド = 値”」と書いていたのが原因でした。詳細は続きを読むでご参照ください。

問題

状況を詳しく説明するとこうです。

「案件モデル」からhasManyで「画像モデル」アソシエートしていて、
つまり案件に対して複数の画像が登録できるようにしているというわけですね。
そして、案件を削除したらその案件に紐付いた画像も一緒に削除したいので、アソシエーションにdependent => trueをセットしています。

今までは案件を削除したら、何の問題も無くその案件に紐付いた画像だけがちゃんと削除されていたんだけど、stableに更新したら案件の削除によってすべての画像が削除されてしまったというのが今回の問題。
「案件モデル」からは別のモデルもアソシエーションしてるんですが、問題が起こっているのは「画像モデル」だけ。

原因を調べてみると「画像モデル」へのアソシエーションだけ「conditions」が設定されていたんですよね。
「”画像モデル.use_flag = 1″」
今までの(RC4まで)CakeだとアソシエーションにセットしたconditionsはModel::findには影響してもModel::deleteには影響しなかったと思うのですよ。
というかそれが当たり前の挙動だと思ってたんだけど、stableにしたらもともとのアソシエーションを無視して、どうも「”画像モデル.use_flag” => “1”」この条件だけで削除してるっぽい。
とりあえずconditionsをコメントアウトして、システムはDBのバックアップから復元して何とかなってるんだけど、これ仕様ではないですよね?
なぜこんなことになるのかまだ原因は調べてないのですが、Model::_deleteDependentあたりが怪しいのかなぁ?と。

もしかして僕の書き方が間違っているのかもしれないから一応案件モデルのソースを貼っておきますね。

<?PHP
class Order extends AModel {
var $name = 'Order';
var $hasOne = array(
"Memo" => array(
"className" => "Memo",
"conditions" => "",
"order" => "",
"dependent" => true,
"foreignKey" => "_order_id"
)
);
var $hasMany = array(
"Mail" => array(
"className" => "Mail",
"conditions" => "",
"order" => "id DESC",
"dependent" => true,
"foreignKey" => "_order_id"
),
"Image" => array(
"className" => "Image",
/*"conditions" => "Image.use_flag = 1",*/
"order" => "Image._image_type_id ASC, Image.id ASC",
"dependent" => true,
),
);
}
?>

なにかお気づきの点などありましたらご指摘いただけると幸いです。

あとで前のバージョンのModelクラスとdiffとってみるので、またわかったことがあれば追記しますね。

追記1

/cake/lib/model/model.phpのdiffを見てみたけどまったく問題なかった。というより変更点はほとんど無いんだね。722行目のif文に条件が1つ追加されているだけだった。念のため追加された条件削っても全削除現象を確認できたからModelクラスは関係無いことが確認できました。
もしかして文字コードがらみで文字化けが起こってるとか凡ミスの気がしてきた…。引き続き調べたいと思います。

追記2

やっとわかった!!
アソシエーションのconditionsはarray(“Image.use_flag” => “1”)と書いてあげなくてはいけなかったんですね!ずっと配列で指定できないもんだと思ってました*[3]
_deleteDependentメソッドで、foreignKey = idとアソシエーションのconditionsをマージする

if ($data['conditions']) {
$conditions = array_merge($data['conditions'], $conditions);
}

という部分があるんだけど、アソシエーションのconditions($data[‘conditions’]ね)が配列じゃないからarray_mergeでエラーが起こって$conditionsがnullになってたんだね。
だからforeignKeyもuse_flagも無視して全てのImageモデルのデータを削除しちゃったんだ。
いや?わかってよかった。みなさんもお気をつけください。

  1. ちなみに僕明日も仕事ですよ! []
  2. なんて献身的な僕。僕エライ!僕最高! []
  3. 確か1.1系はべた書きでしたよね?ついこの間まではそのままで動いていたんだけど、どっかでarray_mergeの処理が入ったんだなぁ。RC4でもすでにこの処理が入っているから、たまたま発見が遅れただけで危ないバグを孕んだまま運用していたとは…stableにアップデートするタイミングでDBのバックアップをとってあったから、このタイミングで問題が起こってマジで助かった。タイミングによっちゃえらいことだったなぁ…超ラッキー。きっとばあちゃんが助けてくれたんだなぁ。ありがとね、ばあちゃん! []

シェアする

  • このエントリーをはてなブックマークに追加

フォローする