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


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.