为了方便调试PHP程序,在程序适当的位置加入日志是明智之举,而不是采用echo来跟踪程序。为此,我写了一个简易的日志程序,来满足我的基本需求,程序如下:

EasyLogger类

/**
 * File: easylogger.php
 * Author: James Tang
 * Date: 2010-08-04 12:49:34
 * (C) 2010 James Tang<[email protected]>. 
 */
class EasyLogger{

    const LEVEL_INFO = 1;

    const LEVEL_DEBUG = 2;

    const LEVEL_WARN = 3;

    const LEVEL_ERROR = 4;

    private $logger_status;

    private $logger_level;

    private $filename;

    private $messages;

    public function __construct ($file)
    {
        $this->filename = $file;
        
        //Set default log level to 3 if SYSTEM_LOG_LEVEL is not defined.
        $this->logger_level = defined('SYSTEM_LOG_LEVEL') ? SYSTEM_LOG_LEVEL : 3;
        
        $this->logger_status = false;
        
        if (!file_exists($file)) {
            touch($file);
        }
        
        $this->messages = NULL;
        
        if ($this->logger_level <= self::LEVEL_ERROR && file_exists($file) && is_writable($file)) {
            $this->logger_status = true;
            $this->messages = array();
        }
    
    }

    public function info ($msg, $source = '', $line = 0)
    {
        $this->log(self::LEVEL_INFO, $msg, $source, $line);
    }

    public function debug ($msg, $source = '', $line = 0)
    {
        $this->log(self::LEVEL_DEBUG, $msg, $source, $line);
    }

    public function warn ($msg, $source = '', $line = 0)
    {
        $this->log(self::LEVEL_WARN, $msg, $source, $line);
    }

    public function error ($msg, $source = '', $line = 0)
    {
        $this->log(self::LEVEL_ERROR, $msg, $source, $line);
    }

    public function close ()
    {
        $this->save_log();
    }

    /**
     * Save log message to file
     *
     * @param integer $level, log level
     * @param string $msg, message
     * @param string $source_file, the source file name
     * @param integer $line, line number
     */
    public function log ($level, $msg, $source_file = '', $line = '')
    {
        
        if ($this->logger_status && $level >= $this->logger_level) {
            
            $message = '';
            
            switch ($level) {
                case self::LEVEL_INFO:
                    $message .= '[INFO]';
                    break;
                
                case self::LEVEL_DEBUG:
                    $message .= '[DEBUG]';
                    break;
                
                case self::LEVEL_WARN:
                    $message .= '[WARN]';
                    break;
                
                case self::LEVEL_ERROR:
                    $message .= '[ERROR]';
                    break;
            
            }
            
            if (strlen($message) > 0) {
                $message .= '[' . date('Y-m-d H:i:s') . ']' . $msg;
                
                if (strlen($source_file) > 0) {
                    $message .= '[source file:' . $source_file;
                    
                    if ($line > 0) {
                        $message .= ', at line ' . $line;
                    }
                    
                    $message .= ']';
                }
                
                $message .= "\n";
                
                $this->messages[] = $message;
            }
        
        }
    
    }

    private function save_log ()
    {
        $hanlder = fopen($this->filename, 'a+');
        
        if ($hanlder && $this->messages && count($this->messages) > 0) {
            
            foreach ($this->messages as $msg) {
                fwrite($hanlder, $msg);
            }
        }
        
        fclose($hanlder);
    
    }

}

其中SYSTEM_LOG_LEVEL用于设定日志的记录级别(1,2,3,4), 即只有日志的级别>=SYSTEM_LOG_LEVEL才写入日志文件,否则忽略。如果SYSTEM_LOG_LEVEL>4(LEVEL_ERROR)将忽略所有日志。使用示例如下:

define('SYSTEM_LOG_LEVEL', 4);

require_once ('easylogger.php');

$logger = new EasyLogger('system.log');

$logger->info('Info message', __FILE__, __LINE__);
$logger->debug('Debug message', __FILE__, __LINE__);
$logger->warn('Warn message', __FILE__, __LINE__);
$logger->error('Error Message', __FILE__, __LINE__);

$logger->close();
echo 'Done';