Создать или написать / добавить в текстовом файле


170

У меня есть веб-сайт, который каждый раз, когда пользователь входит или выходит из системы, сохраняет его в текстовом файле.

Мой код не работает при добавлении данных или создании текстового файла, если он не существует .. Вот пример кода

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

Кажется, он не добавляется к следующей строке после повторного открытия.

Кроме того, я думаю, что это также приведет к ошибке в ситуации, когда два пользователя будут входить в систему одновременно, повлияет ли это на открытие текстового файла и сохранение его впоследствии?

Ответы:


337

Попробуйте что-то вроде этого:

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

5
это создает текстовый файл, если он не существует?
— Джерахмил Асебуш

5
Да, это создать текстовый файл logs.txtи добавить содержимое в нем
— SpencerX

5
у меня есть вопрос. используя LOCK_EX. я знаю, что это предотвратит одновременную запись в файл. но что будет с другим?
— Джерахмил Асебуш

13
php.net/manual/en/function.file-put-contents.php Эта функция возвращает количество байтов, записанных в файл, или FALSE при ошибке. Просто если кому-то интересно.
— Мастер Джеймс

7
@JerahmeelAcebuche Второй процесс, пытающийся получить блокировку, будет «блокировать до получения запрошенной блокировки» ( источник ). Другими словами, второй процесс будет ожидать, пока первый не закроет файл и не снимет блокировку.
— Риного

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. это не работает. это работает для вас?
— Джерахмил Асебуш

1
это работает, если ситуация произойдет, как я уже сказал?
— Джерахмил Асебуш

1
aфлаг будет создать файл , если он не не существует и не имеет значения , что убедитесь , что вы действительно appendновый текст. Для этого \nэто работает, но только если внутри двойных кавычек "не одиночные кавычки'
— Валентин Мерсье

Я имею в виду ситуацию, когда два пользователя входят в разные браузеры. Затем php откроет файл в двух браузерах одновременно и обновит его одновременно. будет ли проблема? \
— Jerahmeel Acebuche

1
О, да, в этом случае будет использоваться база данных SQL, она имеет встроенный движок, чтобы избежать гоночных условий. Но это совершенно новый вопрос.
— Валентин Мерсье

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! Я не ожидал найти это, когда нашел эту страницу ... но на самом деле это основа гораздо лучшего решения, чем то, что я изначально планировал реализовать.
— Майк Картер

4

Это работает для меня, написание (создание также) и / или добавление контента в том же режиме.

$fp = fopen("MyFile.txt", "a+") 

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');.
— ToolmakerSteve

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 добавляет новый стандартный подспецификатор («x»), поддерживаемый PHP, который может быть добавлен к любому спецификатору «w» (для формирования «wx», «wbx», «w + x» или «w + bx»). "/" WB + х "). Этот подспецификатор заставляет функцию завершиться ошибкой, если файл существует, вместо того, чтобы перезаписывать его.

Кроме того, в PHP 5.2.6 был добавлен основной открытый режим 'c'. Вы не можете комбинировать «c» с «a», «r», «w». «С» открывает файл только для записи. Если файл не существует, он создается. Если он существует, он не усекается (в отличие от 'w'), и вызов этой функции не выполняется (как в случае с 'x'). 'c +' Открыть файл для чтения и записи; в противном случае он ведет себя так же, как «с».

Кроме того, в PHP 7.1.2 была добавлена ​​опция 'e', ​​которую можно комбинировать с другими режимами. Он установил флаг close-on-exec для открытого дескриптора файла. Доступно только в PHP, скомпилированном в соответствии с POSIX.1-2008.

Таким образом, для задачи, как вы ее описали, лучшим режимом открытия файла будет «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);
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.