在文本文件中创建或写入/附加


170

我有一个网站,每次用户登录或注销时,我都会将其保存到文本文件中。

如果不存在附加数据或创建文本文件,我的代码将不起作用。这是示例代码

$myfile = fopen("logs.txt", "wr") or die("Unable to open file!");
$txt = "user id date";
fwrite($myfile, $txt);
fclose($myfile);

再次打开它后,它似乎没有追加到下一行。

另外,我认为在两个用户同时登录的情况下也会出现错误,会影响打开文本文件并随后保存吗?

Answers:


337

尝试这样的事情:

 $txt = "user id date";
 $myfile = file_put_contents('logs.txt', $txt.PHP_EOL , FILE_APPEND | LOCK_EX);

5
如果不存在,这会创建一个文本文件吗?
Jerahmeel Acebuche 2014年

5
是的,它会创建文本文件logs.txt并在其中添加内容
SpencerX 2014年

5
我有个问题。使用LOCK_EX。我知道这将阻止其他人同时写入文件。但是另一个会发生什么呢?
Jerahmeel Acebuche 2014年

13
php.net/manual/en/function.file-put-contents.php此函数返回写入文件的字节数,否则返回FALSE。就算有人在想。
詹姆斯大师

7
@JerahmeelAcebuche尝试获取锁的第二个过程“将阻塞,直到获取请求的锁为止”()。换句话说,第二个进程将等待,直到第一个进程关闭了文件并释放了锁。
rinogo '18

102

使用a模式。它代表append

$myfile = fopen("logs.txt", "a") or die("Unable to open file!");
$txt = "user id date";
fwrite($myfile, "\n". $txt);
fclose($myfile);

我也有\ n的问题。这是行不通的。对你有用吗?
Jerahmeel Acebuche 2014年

1
如果情况如我所说发生了,这项工作有效吗?
Jerahmeel Acebuche 2014年

1
a如果该文件不存在,则该标志将创建该文件,并且无论使用何种方式确保您确实是append新文本。对于\n它的工作原理,但只有当内部的双引号"不是单引号'
瓦伦丁名士

我的意思是两个用户登录不同浏览器时的情况。然后php将同时在两个浏览器上打开文件,并同时更新它。会不会有问题?\
Jerahmeel Acebuche 2014年

1
哦,是的,在这种情况下将使用SQL数据库,它具有一个内置的引擎来避免出现竞争情况。但这是一个全新的问题。
Valentin Mercier 2014年

10

您可以通过OO方法来实现,这只是一种替代方法,而且很灵活:

class Logger {

    private
        $file,
        $timestamp;

    public function __construct($filename) {
        $this->file = $filename;
    }

    public function setTimestamp($format) {
        $this->timestamp = date($format)." » ";
    }

    public function putLog($insert) {
        if (isset($this->timestamp)) {
            file_put_contents($this->file, $this->timestamp.$insert."<br>", FILE_APPEND);
        } else {
            trigger_error("Timestamp not set", E_USER_ERROR);
        }
    }

    public function getLog() {
        $content = @file_get_contents($this->file);
        return $content;
    }

}

然后像这样使用它..假设您已经user_name存储在一个会话中(半伪代码):

$log = new Logger("log.txt");
$log->setTimestamp("D M d 'y h.i A");

if (user logs in) {
    $log->putLog("Successful Login: ".$_SESSION["user_name"]);
}
if (user logs out) {
    $log->putLog("Logout: ".$_SESSION["user_name"]);
}

检查您的日志与此:

$log->getLog();

结果就像:

Sun Jul 02 '17 05.45 PM » Successful Login: JohnDoe
Sun Jul 02 '17 05.46 PM » Logout: JohnDoe


github.com/thielicious/Logger


1
非常感谢Logger类!当我找到此页面时,我没想到会发现它,但是实际上,这是比我最初计划实现的解决方案更好的基础。
迈克·卡特


3

试试这个代码:

function logErr($data){
  $logPath = __DIR__. "/../logs/logs.txt";
  $mode = (!file_exists($logPath)) ? 'w':'a';
  $logfile = fopen($logPath, $mode);
  fwrite($logfile, "\r\n". $data);
  fclose($logfile);
}

我总是这样使用它,并且可以工作...


1
没有理由这样做(!file_exists($logPath)) ? 'w':'a'- a当文件不存在时,该选项已经具有正确的行为。因此,可以通过删除行$mode = ...;并将下一行更改为来简化此答案$logfile = fopen($logPath, 'a');
制造商史蒂夫(Steve)

2

您的代码中没有“ wr”这样的文件打开模式:

fopen("logs.txt", "wr") 

PHP http://php.net/manual/en/function.fopen.php中的文件打开模式与C中的相同:http : //www.cplusplus.com/reference/cstdio/fopen/

主要有以下几种打开模式:“ r”表示读取,“ w”表示写入,“ a”表示追加,您无法将它们组合在一起。您可以添加其他修饰符,例如“ +”代表更新,“ b”代表二进制。新的C标准添加了PHP支持的新标准子说明符(“ x”),可以将其附加到任何“ w”说明符(以形成“ wx”,“ wbx”,“ w + x”或“ w + bx” “ /” wb + x“)。如果文件存在,此子说明符将强制该函数失败,而不是覆盖它。

除此之外,在PHP 5.2.6中,添加了“ c”主打开模式。您不能将“ c”与“ a”,“ r”,“ w”组合。“ c”打开仅用于写入的文件。如果该文件不存在,则会创建它。如果存在,则它既不会被截断(与“ w”相对),也不会对该函数的调用失败(与“ x”的情况相同)。'c +'打开文件进行读写;否则,其行为与“ c”相同。

另外,在PHP 7.1.2中,添加了'e'选项,该选项可以与其他模式结合使用。它在打开的文件描述符上设置close-on-exec标志。仅在POSIX.1-2008兼容系统上编译的PHP中可用。

因此,对于您所描述的任务,最佳文件打开模式将为“ a”。它打开文件仅用于写入。它将文件指针放在文件末尾。如果该文件不存在,它将尝试创建它。在这种模式下,fseek()不起作用,写操作总是被附加。

正如上面已经指出的,这是您需要的:

fopen("logs.txt", "a") 

0

尽管有很多方法可以做到这一点。但是,如果您想以一种简单的方式进行操作,并且想要在将文本写入日志文件之前对其进行格式化。您可以为此创建一个辅助函数。

if (!function_exists('logIt')) {
    function logIt($logMe)
    {
        $logFilePath = storage_path('logs/cron.log.'.date('Y-m-d').'.log');
        $cronLogFile = fopen($logFilePath, "a");
        fwrite($cronLogFile, date('Y-m-d H:i:s'). ' : ' .$logMe. PHP_EOL);
        fclose($cronLogFile);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.