如何在php中创建日志文件

110

我想为我的系统创建一个日志文件,以便记录/注册系统内部执行的每个操作。但我不知道如何做。

比如说,我有这段PHP代码来执行登录功能。

public function hasAccess($username,$password){
    $form = array();
    $form['username'] = $username;
    $form['password'] = $password;
    

    $securityDAO = $this->getDAO('SecurityDAO');
    $result = $securityDAO->hasAccess($form);
    //var_dump($form);
    //var_dump($result);
    if($result[0]['success']=='1'){
        $this->Session->add('user_id', $result[0]['id']);
        //$this->Session->add('username', $result[0]['username']);
        //$this->Session->add('roleid', $result[0]['roleid']);
        return $this->status(0,true,'auth.success',$result);
    }else{
        return $this->status(0,false,'auth.failed',$result);
    }
}

现在我想创建一个名为“今天日期”的日志文件,然后当该函数用于登录时,它将写入用户已登录,其他功能也是如此。但我每天只想要一个文件。

有没有人能够友善地指导和教我应该如何编写代码?

11个回答

190

要写入一个日志文件并每天创建一个新文件,您可以将date("j.n.Y")作为文件名的一部分。

//Something to write to txt log
$log  = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
        "Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
        "User: ".$username.PHP_EOL.
        "-------------------------".PHP_EOL;
//Save string to log, use FILE_APPEND to append.
file_put_contents('./log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

所以你需要将这个放在你的hasAccess()方法中。

public function hasAccess($username,$password){
    $form = array();
    $form['username'] = $username;
    $form['password'] = $password;

    $securityDAO = $this->getDAO('SecurityDAO');
    $result = $securityDAO->hasAccess($form);

    //Write action to txt log
    $log  = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
            "Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
            "User: ".$username.PHP_EOL.
            "-------------------------".PHP_EOL;
    //-
    file_put_contents('./log_'.date("j.n.Y").'.txt', $log, FILE_APPEND);

    if($result[0]['success']=='1'){
        $this->Session->add('user_id', $result[0]['id']);
        //$this->Session->add('username', $result[0]['username']);
        //$this->Session->add('roleid', $result[0]['roleid']);
        return $this->status(0,true,'auth.success',$result);
    }else{
        return $this->status(0,false,'auth.failed',$result);
    }
}

我尝试将我的系统放在基于Linux的计算机上,现在日志文件出现了权限问题。我该如何解决? - maecy m
4
绝对不会以明文形式存储密码,无论是在日志文件中还是其他地方。 - smoothware
1
补充一下:"PHP_EOL类似于根据操作系统平台选择"\n"或"\r\n"。我讨厌很多的\n\n\n\n's ;p - Lawrence Cherone Nov 11 '13 at 4:55" EOL简单地表示行尾。自PHP 5.0.2以来可用。在此处阅读更多信息: https://www.php.net/manual/en/reserved.constants.php - kPieczonka
特别是日志文件。有很多应用程序要求将密码存储在明文配置文件中,这是一个相当被接受的规范。然而,包含这些文件的文件夹需要进行权限锁定,并且其中只能包含服务特定的密码,绝不能包含真实的用户密码。 - Robert Talada
4
如果有两个脚本同时尝试写入日志,并且脚本1的数据量非常大,以至于不能在单个write()中写入所有数据(此时file_put_contents将自动执行第二个write()来尝试写入剩余数据),那么代码不安全,因为它无法防止并发写入。如果脚本2在脚本1的第一个write()之后但在脚本1的第二个write()之前写入其日志,则会导致日志混乱。您可以通过将LOCK_EX与FILE_APPEND(按位或在一起)组合使用,然后script2将等待script1完全完成,以避免这种潜在问题。 - hanshenrik
file_put_contents是一个糟糕的函数,会导致其后面的代码偶尔失败。 - Pyromonk

43

在PHP中创建日志文件,你需要通过函数传递数据来完成它,它会为你创建日志文件。

function wh_log($log_msg)
{
    $log_filename = "log";
    if (!file_exists($log_filename)) 
    {
        // create directory/folder uploads.
        mkdir($log_filename, 0777, true);
    }
    $log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
    // if you don't add `FILE_APPEND`, the file will be erased each time you add a log
    file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
} 
// call to function
wh_log("this is my log message");

16

同意@jon的答案。只需修改路径以在root内创建log目录。


 function wh_log($log_msg) {
    $log_filename = $_SERVER['DOCUMENT_ROOT']."/log";
    if (!file_exists($log_filename))
    {
        // create directory/folder uploads.
        mkdir($log_filename, 0777, true);
    }
    $log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
    file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
}

wh_log('log to file');

刚刚添加了$_SERVER['DOCUMENT_ROOT']


12
请查看此文档:

http://php.net/manual/en/function.error-log.php

示例:
<?php
// Send notification through the server log if we can not
// connect to the database.
if (!Ora_Logon($username, $password)) {
    error_log("Oracle database not available!", 0);
}

// Notify administrator by email if we run out of FOO
if (!($foo = allocate_new_foo())) {
    error_log("Big trouble, we're all out of FOOs!", 1,
               "operator@example.com");
}

// another way to call error_log():
error_log("You messed up!", 3, "/var/tmp/my-errors.log");
?>

6

请检查这段代码,对我来说它运行良好。

$data = array('shopid'=>3,'version'=> 1,'value=>1');  //here $data is dummy varaible

error_log(print_r($data,true), 3, $_SERVER['DOCUMENT_ROOT']."/your-file-name.log");

//In $data we can mention the error messege and create the log

在上面的代码中,error_log行足以在您的根文件夹中创建一个新的日志文件,print_r($data,true)数据中提到了您真正想要打印在那个日志文件中的内容。 - Pasupathi Thangavel

3
您可以使用内置函数trigger_error()来触发用户错误/警告/通知,使用set_error_handler()来处理它们。在您的错误处理程序中,您可能希望使用error_log()file_put_contents()将所有记录存储到文件中。要每天拥有一个单独的文件,只需使用类似于sprintf('%s.log', date('Y-m-d'))的文件名即可。现在您应该知道从哪里开始了... :)

1
我该如何编写它?您介意能给我一个示例代码吗?如果可以的话。谢谢。 - maecy m

1
这是我的工作代码。感谢Paulo提供的链接。您需要创建一个自定义错误处理程序,并使用正确的$errno异常调用trigger_error函数,即使它不是一个错误。确保您可以在没有管理员访问权限的情况下写入日志文件目录。
<?php
    $logfile_dir = "C:\workspace\logs\\";   // or "/var/log/" for Linux
    $logfile = $logfile_dir . "php_" . date("y-m-d") . ".log";
    $logfile_delete_days = 30;

    function error_handler($errno, $errstr, $errfile, $errline)
    {
        global $logfile_dir, $logfile, $logfile_delete_days;

        if (!(error_reporting() & $errno)) {
            // This error code is not included in error_reporting, so let it fall
            // through to the standard PHP error handler
            return false;
        }

        $filename = basename($errfile);

        switch ($errno) {
            case E_USER_ERROR:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "ERROR >> message = [$errno] $errstr\n", FILE_APPEND | LOCK_EX);
                exit(1);
                break;

            case E_USER_WARNING:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "WARNING >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;

            case E_USER_NOTICE:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "NOTICE >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;

            default:
                file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "UNKNOWN >> message = $errstr\n", FILE_APPEND | LOCK_EX);
                break;
        }

        // delete any files older than 30 days
        $files = glob($logfile_dir . "*");
        $now   = time();

        foreach ($files as $file)
            if (is_file($file))
                if ($now - filemtime($file) >= 60 * 60 * 24 * $logfile_delete_days)
                    unlink($file);

        return true;    // Don't execute PHP internal error handler
    }

    set_error_handler("error_handler");

    trigger_error("testing 1,2,3", E_USER_NOTICE);
?>

你会如何用面向对象的PHP编写这个代码? - TRS7
@TRS7 对不起,我不确定。我在每个 PHP 文件中单独调用 set_error_handler - xinthose

0
一个自定义的日志函数(适用于php服务器):
特点:
日志将对公众隐藏(无需在服务器上进行设置)
易于阅读日志数据
function log_it($info)
{
$filename = $_SERVER['DOCUMENT_ROOT'] . '/' . '1LOGS.php';
$dieCode = "<?php die();?>";
$fileStart = @file_get_contents($filename, false, null, 0, 14);
if ($fileStart) {
    if ($fileStart !== $dieCode)
        file_put_contents($filename, $dieCode . file_get_contents($filename));
} else file_put_contents($filename, $dieCode);

if (is_string($info) || is_int($info) || is_float($info)) $txt = '    ' . $info;
elseif (is_array($info) || is_object($info)) $txt = PHP_EOL . '    ' . print_r($info, true);
else $txt = '    ' . 'Data Type: ' . gettype($info);
file_put_contents(
    $filename,
    PHP_EOL . '>>> ( Date:' . date("Y:m:d H:i:s") . ' )' . $txt,
    FILE_APPEND
);
}

请提供改进的空间


0
请使用以下函数:
// Enable error reporting
ini_set('display_errors', 1);
//Report runtime errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//error_reporting(E_ALL & ~E_NOTICE);
// Tell php where your custom php error log is
ini_set('error_log', 'php_error.log');

$dateTime=date("Y-m-d H:i:s");
$ip= $_SERVER['REMOTE_ADDR'];
$errorString="Error occured on time $dateTime by ip $ip";
$php_error_msg.=$errorString;
// Append the error message to the php-error log
//error_log($php_error_msg);
error_log("A custom error has been triggered",1,"email_address","From: email_address");

上述函数将创建一个名为php_error的日志文件,其中包含适当的描述,并发送电子邮件。


0

使用此函数来打印日志,这将在log文件夹中创建日志文件。如果不存在,则创建日志文件夹。

logger("Your msg in log ", "Filename you want ", "Data to be log string or array or object");


function logger($logMsg="logger", $filename="logger", $logData=""){     
            $log  = date("j.n.Y h:i:s")." || $logMsg : ".print_r($logData,1).PHP_EOL .                  
            "-------------------------".PHP_EOL;
            file_put_contents('./log/'.$filename.date("j.n.Y").'.log', $log, FILE_APPEND);                      
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接