Створіть або напишіть / додайте у текстовому файлі


170

У мене є веб-сайт, який кожного разу, коли користувач входить або виходить із системи, я зберігаю його у текстовому файлі.

Мій код не працює при додаванні даних або створенні текстового файлу, якщо його не існує. Ось зразок коду

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

Здається, він не додається до наступного рядка після того, як я його знову відкрию.

Також я думаю, що це також призведе до помилки в ситуації, коли 2 користувачі входять одночасно, чи вплине це на відкриття текстового файлу та збереження його згодом?

Відповіді:


337

Спробуйте щось подібне:

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

5
це створює текстовий файл, якщо його не існує?
Jerahmeel Acebuche

5
Так, створіть текстовий файл logs.txtі додайте до нього вміст
SpencerX

5
У мене є питання. за допомогою LOCK_EX. я знаю, що це не дозволить комусь писати у файл одночасно. але що буде з іншим?
Jerahmeel Acebuche

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

7
@JerahmeelAcebuche Другий процес спроби придбати замок "заблокується, поки не буде придбано запитуваний замок" ( джерело ). Іншими словами, другий процес буде чекати, поки перший закриє файл і випустить замок.
rinogo

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

1
чи працює це, якщо ситуація станеться так, як я вже сказав?
Jerahmeel Acebuche

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 + x "). Цей субспецифікатор змушує функцію вийти з ладу, якщо файл існує замість того, щоб перезаписати його.

Крім того, у PHP 5.2.6 додано головний відкритий режим 'c'. Ви не можете поєднувати "c" з "a", "r", "w". 'C' відкриває файл лише для запису. Якщо файл не існує, він створюється. Якщо вона існує, вона не є ні усіченою (на відміну від 'w'), ні виклик цієї функції не працює (як у випадку з 'x'). 'c +' Відкрийте файл для читання та запису; в іншому випадку вона має таку саму поведінку, як "c".

Крім того, і в PHP 7.1.2 додано параметр 'e', ​​який можна комбінувати з іншими режимами. Він встановлює прапор закритого рівня на відкритому дескрипторі файлу. Доступний лише у 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.