端くれプログラマの備忘録 PHP [PHP] アクセスログを記録するクラスを書いてみた

[PHP] アクセスログを記録するクラスを書いてみた

Apacheの生ログとは別に、特定のPHPファイルのアクセスログだけを記録したいことがある。そんなことが簡単に出来るように、いろいろ使い回しが利きそうな汎用のアクセスログクラスを書いてみた。

PHPソース

<?php
 
// ログファイルを出力するサーバー上のディレクトリを指定する。
// このディレクトリに日付をファイル名とするCSVファイルが作成される。
define('LOGS_PATH', "/xxxx/xxxx/xxxx/");
 
class AccessLog {
    private $scriptName; // $_SERVER['SCRIPT_NAME']
    private $requestUri; // $_SERVER['REQUEST_URI']
    private $authUser;   // $_SERVER['PHP_AUTH_USER']
    private $referer;    // $_SERVER['HTTP_REFERER']
    private $remoteHost; // gethostbyaddr($_SERVER['REMOTE_ADDR'])
    private $userAgent;  // $_SERVER['HTTP_USER_AGENT']
 
    function __construct() {
        if (!file_exists(LOGS_PATH)) {
            mkdir(LOGS_PATH);
        }
        $file = LOGS_PATH . date('Ymd') . '.csv';
        $this->setInfo();
        $this->writeLog($file, $this->formatLog());
    }
 
    private function setInfo() {
        $this->scriptName = @$_SERVER['SCRIPT_NAME'];
        $this->requestUri = @$_SERVER['REQUEST_URI'];
        $this->authUser = @$_SERVER['PHP_AUTH_USER'];
        $this->referer = @$_SERVER['HTTP_REFERER'];
 
        $software = @$_SERVER['SERVER_SOFTWARE'];
        if (strpos($software, "nginx") === FALSE) {
            $remoteAddr = @$_SERVER['REMOTE_ADDR'];
        } else {
            $remoteAddr = @$_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        if ($remoteAddr) {
            $this->remoteHost = gethostbyaddr($remoteAddr);
        } else {
            $this->remoteHost = $remoteAddr;
        }
        $this->userAgent = @$_SERVER['HTTP_USER_AGENT'];
    }
 
    private function formatLog() {
        return date('Y/m/d H:i:s') . ',"' .
               $this->scriptName . '","' .
               $this->referer . '","' .
               $this->userAgent . '","' .
               $this->remoteHost . '","' .
               $this->requestUri . '","' .
               $this->authUser . "\"\n";
    }
 
    private function writeLog($file, $log) {
        $fh = fopen($file, 'a');
        if ($fh) {
            if (flock($fh, LOCK_EX)) {
                fwrite($fh, $log);
                fflush($fh);
                flock($fh, LOCK_UN);
            }
            fclose($fh);
        }
    }
}
 
$obj = new AccessLog();
 
?>

使い方

アクセスログを記録したいPHPファイルの冒頭にインクルードするだけ。

<?php
require_once("AccessLog.php")
.....
?>

ログ出力例

2014/05/27 09:55:27,"/index.php","","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0","xxx.xxx.xxx.xxx","/",""
2014/05/27 09:57:41,"/products.php","http://www.example.com/","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0","xxx.xxx.xxx.xxx","/",""
2014/05/27 10:03:32,"/products/item1.php","http://www.example.com/products.php","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0","xxx.xxx.xxx.xxx","",""