Write to a log file with PHP

As I caught myself in process of writing PHP “log” function several times I have finally decided to create a simple Logging PHP class. After Logging class initialization, first call of lwrite method will open log file implicitly and write line to the file. Every other lwrite will use already opened file pointer until closing file with lclose. It is always a good idea to close a file when it’s over. This should prevent file from corruption and overhead in closing file is negligible.

Before you read further, I also wrote a post how to Log PHP errors to the separate file, if you are looking for such information.

How to use Logging class:

// Logging class initialization
$log = new Logging();

// set path and name of log file (optional)
$log->lfile('/tmp/mylog.txt');

// write message to the log file
$log->lwrite('Test message1');
$log->lwrite('Test message2');
$log->lwrite('Test message3');

// close log file
$log->lclose();

Output in mylog.txt will look like:

[10/Jun/2012:10:36:19] (test) Test message1
[10/Jun/2012:10:36:19] (test) Test message2
[10/Jun/2012:10:36:19] (test) Test message3

Logging class source code:

/** 
 * Logging class:
 * - contains lfile, lwrite and lclose public methods
 * - lfile sets path and name of log file
 * - lwrite writes message to the log file (and implicitly opens log file)
 * - lclose closes log file
 * - first call of lwrite method will open log file implicitly
 * - message is written with the following format: [d/M/Y:H:i:s] (script name) message
 */
class Logging {
    // declare log file and file pointer as private properties
    private $log_file, $fp;
    // set log file (path and name)
    public function lfile($path) {
        $this->log_file = $path;
    }
    // write message to the log file
    public function lwrite($message) {
        // if file pointer doesn't exist, then open log file
        if (!is_resource($this->fp)) {
            $this->lopen();
        }
        // define script name
        $script_name = pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME);
        // define current time and suppress E_WARNING if using the system TZ settings
        // (don't forget to set the INI setting date.timezone)
        $time = @date('[d/M/Y:H:i:s]');
        // write current time, script name and message to the log file
        fwrite($this->fp, "$time ($script_name) $message" . PHP_EOL);
    }
    // close log file (it's always a good idea to close a file when you're done with it)
    public function lclose() {
        fclose($this->fp);
    }
    // open log file (private method)
    private function lopen() {
        // in case of Windows set default log file
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $log_file_default = 'c:/php/logfile.txt';
        }
        // set default log file for Linux and other systems
        else {
            $log_file_default = '/tmp/logfile.txt';
        }
        // define log file from lfile method or use previously set default
        $lfile = $this->log_file ? $this->log_file : $log_file_default;
        // open log file for writing only and place file pointer at the end of the file
        // (if the file does not exist, try to create it)
        $this->fp = fopen($lfile, 'a') or exit("Can't open $lfile!");
    }
}

For PHP prior to version 5.2.0 you will have to replace or change line with built-in PHP function pathinfo() because PATHINFO_FILENAME constant was added in PHP 5.2.0

// for PHP 5.2.0+
$script_name = pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME);

// for PHP before version 5.2.0
$script_name = basename($_SERVER['PHP_SELF']);
$script_name = substr($script_name, 0, -4); // php extension and dot are not needed

If you want to send a message to the PHP’s system logger, please see the error_log PHP command.

39 thoughts on “Write to a log file with PHP”

  1. looks good, but it could be improved by using the built-in PHP function pathinfo() to get your $script_name

  2. PHP has a really big list of functions and now I know one function more – thank you Steve. After I improved lwrite method with pathinfo, my PHP code is shorter and simpler.

  3. Vasim,
    you can specify error log path in /etc/php.ini like I described in Log PHP errors to the separate file or you can define your own error handling and logging functions.

    Here is part from the PHP error handling and logging manual:
    “With the logging functions, you can send messages directly to other machines, to an email (or email to pager gateway!), to system logs, etc., so you can selectively log and monitor the most important parts of your applications and websites. The error reporting functions allow you to customize what level and kind of error feedback is given, ranging from simple notices to customized functions returned during errors.”

    PHP manual also contains nice example of using the error handling capabilities in PHP.
    Hope this informations will help you.

  4. @viettel – Yes you can read any file with PHP if you have read permissions. Please be aware that access_log can be huge (like 100MB or more) and reading / processing will be resource intensive task.

  5. This is very nice!!
    Now I want to put the error lines in red colour should it be possible?

  6. @Abhishek – My intention was to write log PHP output to the ordinary file and to read it with text editor (like vi). But if you want to read log file with browser – you can modify PHP script to wrap lines with <span style=”color:red”></span> … This lines will be red.

  7. hello, i’m still beginner in php. i want my php to use data in log file and filter it on linux platform. For example i want my php to take data in log file in my honeypot. then the raw data will be filter into certain category. can anybody help me because i need to use it into my project.

  8. Thanks for sharing. Though couple questions. Do you run in any concurency issues? Shoul’d you lock the file? (Not sure how it is done with PHP). Also, isn’t similar can be achieved simply by using
    file_put_contents function?

  9. This is simple function and only one line is written per logging so I assume that concurrency (file locking) wasn’t needed in such case. Anyway, PHP has flock function and is possible to extend Logging class to support file locking. And about file_put_contents … You’re probably right, but file_put_contents is available since PHP5 so this will not work on PHP4 engines – on the other hand, who still uses PHP4 ;)

  10. Nice script! I’ve modified your logger class so that I can pass a different log file to use in the constructor. Thanks for sharing!

  11. Thanks for sharing this greate work!

    Optionally you can add this function to close the file pointer.

    private function __destruct() {
        fclose($this->fp);
    }
    

Comments are closed.