PHPでもログ出力用ライブラリは、いろいろあるようです。(log4php PEAR::Log)
また車輪を作ってみました。例によって、最低限のログを出力するための機能を、標準関数error_logを使って実装した。
1
2
3
4
5
6
7
| <?php
require_once("Log.php");
Log::error("エラー発生");
Log::warn("警告 test");
Log::info("情報 test");
Log::debug(array('hoge' => 12));
?> |
<?php
require_once("Log.php");
Log::error("エラー発生");
Log::warn("警告 test");
Log::info("情報 test");
Log::debug(array('hoge' => 12));
?>
の出力結果が下になるようにした。
2007/06/03 15:06:00 ERROR エラー発生
2007/06/03 15:06:00 WARN 警告 test
2007/06/03 15:06:00 INFO 情報 test
2007/06/03 15:06:00 DEBUG array (
2007/06/03 15:06:00 DEBUG 'hoge' => 12,
2007/06/03 15:06:00 DEBUG ) |
2007/06/03 15:06:00 ERROR エラー発生
2007/06/03 15:06:00 WARN 警告 test
2007/06/03 15:06:00 INFO 情報 test
2007/06/03 15:06:00 DEBUG array (
2007/06/03 15:06:00 DEBUG 'hoge' => 12,
2007/06/03 15:06:00 DEBUG )
Log.php
ログファイル名とログ出力レベルは、定数指定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| <?php
define('LOG_FILE', 'log/phpapp.log');
define('LOG_LEVEL', 4); //0:none 1:error 2:waring 3:info 4:debug
define('LOG_OUTPUT_PLACE', true); //true:クラス名と行番号を出力する false:出力しない
class Log {
public static function debug($o) {
if (LOG_LEVEL < 4) return;
Log::output($o, "DEBUG", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function info($o) {
if (LOG_LEVEL < 3) return;
Log::output($o, "INFO ", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function warn($o) {
if (LOG_LEVEL < 2) return;
Log::output($o, "WARN ", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function error($o) {
if (LOG_LEVEL < 1) return;
Log::output($o, "ERROR", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function error_and_die($o) {
if (LOG_LEVEL < 1) return;
Log::output($o, "ERROR", debug_backtrace());
die($o);
}
private static function output($o, $mode, $traces) {
if (is_numeric($o) || is_string($o)) {
Log::output_message($o, $mode, $traces);
} else {
Log::output_message(var_export($o, true), $mode, $traces);
}
}
private static function output_message($str, $mode, $traces) {
$now = date("Y/m/d H:i:s");
$place = '';
if ($traces && is_array($traces) && count($traces) > 0) {
$trace = $traces[0];
$place = "{$trace['file']}({$trace['line']})";
}
foreach (split("\n", $str) as $line) {
error_log("$now $mode $place $line\r\n", 3, LOG_FILE);
}
}
}
?> |
<?php
define('LOG_FILE', 'log/phpapp.log');
define('LOG_LEVEL', 4); //0:none 1:error 2:waring 3:info 4:debug
define('LOG_OUTPUT_PLACE', true); //true:クラス名と行番号を出力する false:出力しない
class Log {
public static function debug($o) {
if (LOG_LEVEL < 4) return;
Log::output($o, "DEBUG", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function info($o) {
if (LOG_LEVEL < 3) return;
Log::output($o, "INFO ", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function warn($o) {
if (LOG_LEVEL < 2) return;
Log::output($o, "WARN ", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function error($o) {
if (LOG_LEVEL < 1) return;
Log::output($o, "ERROR", LOG_OUTPUT_PLACE ? debug_backtrace() : null);
}
public static function error_and_die($o) {
if (LOG_LEVEL < 1) return;
Log::output($o, "ERROR", debug_backtrace());
die($o);
}
private static function output($o, $mode, $traces) {
if (is_numeric($o) || is_string($o)) {
Log::output_message($o, $mode, $traces);
} else {
Log::output_message(var_export($o, true), $mode, $traces);
}
}
private static function output_message($str, $mode, $traces) {
$now = date("Y/m/d H:i:s");
$place = '';
if ($traces && is_array($traces) && count($traces) > 0) {
$trace = $traces[0];
$place = "{$trace['file']}({$trace['line']})";
}
foreach (split("\n", $str) as $line) {
error_log("$now $mode $place $line\r\n", 3, LOG_FILE);
}
}
}
?>
2010/05/31 ログを出力した位置を出力するように修正したバージョンに変更しました。
まあ、面白みもないものです。ログなので。
実は、debugとかerrorは、本当のところ関数として実装したかったのですが、別のモジュールが使っていたため、関数の重複定義になってしまった。
そのため、classのメソッドにしてしまいました。
PHP5では、名前空間(namespace)がサポートされた。これにより、クラス、変数、定数、関数を名前空間内に押し込めることができる。
http://www.atmarkit.co.jp/flinux/special/php5/php5c.html
namespaceは、必要だろうと思ったら、PHP5でサポートされてるらしいです。
あと、__callで、publicメソッドを纏めてしまおうとしたんですが、__callはクラスメソッドに対しては機能しないようでした。