Fusicの中野です。
表題のとおり、CakePHPのログに関する小ネタを紹介します。
ちなみに、使っているCakePHPのバージョンは1.3です。(CakePHP2.xなんて知りません)
CakePHPでConfigure::read(“debug”) > 1の場合は画面にSQLのログが表示されます。
ですが、運用中ではPHPのエラー表示などがされないように、Configure::read(“debug”) == 0の状態ではないかと思います。
そうなると、すこしだけSQLの確認をしたいときなどちょっと面倒ですよね。
CakePHPはConfigure::read(“debug”) > 1の場合、SQLのログはDboSourceの_queriesLogというメンバの配列に格納されていて、どうやらその配列の中身を画面に出力しているようです。
そこで、こいつの中身が取れれば解決できるので・・・
$db =& ConnectionManager::getDataSource($Model->useDbConfig); $db->fullDebug = true; // ここがfalseだとログを保存しない。$db->fullDebug = Configure::read() > 1みたいになってます。 $db->_queriesLogMax = 200; // SQLがこの件数こえると配列に保存しないよ的なもの。 |
みたいなことをfindを実行する前に書いてあげれば、_queriesLogに登録されるようです。
だけど、これだと少々めんどいのでBehaviorにまとめてみましょう。
class QueryLogBehavior extends ModelBehavior { var $__settings = array(); var $_queriesLogMax = 999; function setup( &$Model, $settings = array() ){ $this->__settings[ $Model->alias ] = array(); } function make_query_key( $Model, $query ){ return get_class( $Model ) . "__" . md5( serialize( $query ) ); } function add_query( $key ){ return "'" . $key . "' = '" . $key . "'"; } function beforeFind( &$Model, $query ){ if( array_key_exists( "log", $query ) and $query["log"] ){ $db =& ConnectionManager::getDataSource($Model->useDbConfig); $db->fullDebug = true; $db->_queriesLogMax = $this->_queriesLogMax; $key = $this->make_query_key( $Model, $query ); // いらないかも。 if( array_key_exists( "conditions", $query ) ){ $query["conditions"][] = $this->add_query( $key ); } else { $query["conditions"] = array( $this->add_query( $key ) ); } $this->__settings[$Model->alias][] = array( $key, $query["log"] ); } return $query; } function afterFind( &$Model, $results, $primary ){ $db =& ConnectionManager::getDataSource($Model->useDbConfig); $db->fullDebug = Configure::read() > 1; $db->_queriesLogMax = 200; $hit_sql = null; $level = LOG_DEBUG; foreach( $this->__settings[$Model->alias] as $keypair ){ list( $key, $level ) = $keypair; foreach( $db->_queriesLog as $index => $query_log ){ if( preg_match( "/^(.*)" . $this->add_query( $key ) . "(.*)$/", $query_log["query"], $regexp )) { $hit_sql = $regexp[1] . "" . $regexp[2]; break; } } } if( !is_null( $hit_sql ) ) $this->log( $hit_sql, $level ); return true; } } |
なんかこんな風に適当にBehaviorを追加して
$this->Hoge->find( "all", array( "contain" => array(), "conditions" => <なんかの条件>, "log" => LOG_INFO ) ); |
みたいにしてあげたら、app/tmp/log/debug.logにSQLが記述されます。これで任意のfindの処理のSQLをログにだしたりできます。
データベースの設定でSQLのログだしとけよとかいうツッコミはなしで。