読者です 読者をやめる 読者になる 読者になる

CakePHPでDBのExceptionが起こった時にどういうSQLを投げたためかをログに吐く

mysql CakePHP

何か変なqueryをMySQLに投げてしまって

2012-05-26 18:23:21 Error: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`user_logs`, CONSTRAINT `user_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))

みたいな感じでPDOExceptionが発生した場合に、どんなSQLを実行したのかがわからなくて困ったので調べた。



debugモードであればqueriesLogに保存されてそれを覗けばわかるのだけど、本番だとqueriesLogには保存されないのでそれだとダメ。
ググっても「queriesLog覗けばいいよ」とか「getLog()実行すればいい」的なのばかり出て来てなかなか欲しい情報にたどり着けず。
# というか、結局エラーが出た時にSQLが調べられればいいのでdebugモードのときみたいに常にある必要はない



で、ソース見たらあった。

<?php
// https://github.com/cakephp/cakephp/blob/master/lib/Cake/Model/Datasource/DboSource.php#L449
		} catch (PDOException $e) {
			if (isset($query->queryString)) {
				$e->queryString = $query->queryString;
			} else {
				$e->queryString = $sql;
			}
			throw $e;
		}

PDEOExceptionが起こった時に$eのqueryStringに突っ込んでる。
なのでexceptionで捕まえた時にコレをそのままログに吐けばいい。



ってことで、AppModelの中でException捕まえて、その中で

<?php
CakeLog::write('error', $e->getMessage());
CakeLog::write('error', $e->queryString);

みたいな感じでログに吐くことにした。
結果、

Error: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`user_logs`, CONSTRAINT `user_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))
Error: INSERT INTO `test`.`user_logs` (`is_error`, `modified`, `created`) VALUES ('1', '2012-05-26 18:23:20', '2012-05-26 18:23:20')

こんな感じでログが吐かれる