くまきち

山と旅と家族が大事。
でも激しい物欲が理性と財布のタガを飛ばす
最近は自転車も乗ってる

CakePHP: Model::save()メソッドのオーバーロード

2009-05-25 20:41:53 | SEまわり
 PHPでは「オーバーロード」と言うらしいので…

 Model::save() メソッドをカスタマイズしたくて、AppModel中で次のように記述した。

function save($data=null, $validate=true, $fieldList=array()) {
$this->log("Saved");
parent::save($data, $validate, $fieldList);
}


 これで、ログを出力してから、保存処理、と進んでくれると思っていたところ、実行結果は、「ヌルの許されないフィールドにヌルデータを保存しようとしました」というエラーだった。

 実行された INSERT 文を見ると、確かに created, modifiedの二つに now() を入れるだけの INSERT 文になっていた。

 モデルの関係は、

Model ← AppModel ← SampleModel


 となっており、SampleModel 中で save() を呼び出しているが、もちろんデータは渡している。

 試しに、AppModel 中の save()メソッド(上の改造をしたとこ)中で、pr($data) としてみたところ、データは入っていた。

 が、parent::save として Model::save() が呼び出されたところではヌルになっている



 はて…


 結果は。


 parent::save() は正しくコールされていた。

 ただ、AppModel::save() が戻り値をちゃんと返してなかったため、コントローラが失敗と判断してエラーメッセージを表示していただけで、実際はデータが保存されていた。

 下のように変更することで、期待通りの動作をした。

function save($data=null, $validate=true, $fieldList=array()) {
$this->log("Saved");
return parent::save($data, $validate, $fieldList);
}


 ミス自体は簡単だが、少し時間を食った。


CakePHP: ログフォーマットのカスタマイズ

2009-05-25 17:20:15 | SEまわり
CakePHP のログ出力の内容をカスタマイズしたいと思った。

log() メソッドは Object クラスに実装されている。

このクラス定義は app ディレクトリの下にではなく、大元の cake/libs の下にあるため、app の下に 独自の object.php を置いても効果がなかった。

仕方ないので、app の下にあるもので一番上位である AppController と AppModel の中で、log() を上書きしてしまうことにする。

今回は、log() の引数メッセージの後ろに、log() を読んだ場所を示すクラス名とメソッド名に加え、クライアントの IP アドレスをくっつけるようにカスタマイズした。

以下のブロックを、app_model.php, app_controller.php の中に記述する。

function log($msg, $type=LOG_ERROR) {
 $class = get_class($this);
 $method = __FUNCTION__;
 $ipaddr = $_SERVER['REMOTE_ADDR'];
 $msg = $msg." in $class::$method Client:$ipaddr";
 parent::log($msg, $type);
}


これで、呼び出し側はこれまでと変わらず、以下のように呼び出せば、上記情報が追加された形でログに記録される。

$this->log("Error");