Erstellen oder Schreiben / Anhängen in eine Textdatei

170

Ich habe eine Website, die jedes Mal, wenn sich ein Benutzer anmeldet oder abmeldet, in einer Textdatei gespeichert wird.

Mein Code funktioniert nicht beim Anhängen von Daten oder beim Erstellen einer Textdatei, wenn diese nicht vorhanden ist. Hier ist der Beispielcode

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

Es scheint, dass es nicht an die nächste Zeile angehängt wird, nachdem ich es wieder geöffnet habe.

Ich denke auch, dass es auch einen Fehler geben würde, wenn sich 2 Benutzer gleichzeitig anmelden. Würde dies das Öffnen der Textdatei und das anschließende Speichern beeinträchtigen?

Jerahmeel Acebuche
quelle

Antworten:

337

Versuchen Sie so etwas:

 $txt = "user id date";
 $myfile = file_put_contents('logs.txt', $txt.PHP_EOL , FILE_APPEND | LOCK_EX);
SpencerX
quelle
5
Erstellt dies eine Textdatei, wenn diese nicht vorhanden ist?
Jerahmeel Acebuche
5
Ja, es erstellt die Textdatei logs.txtund fügt den Inhalt darin hinzu
SpencerX
5
Ich habe eine Frage. mit dem LOCK_EX. Ich weiß, dass dies verhindert, dass andere gleichzeitig in die Datei schreiben. aber was wird mit dem anderen passieren?
Jerahmeel Acebuche
13
php.net/manual/en/function.file-put-contents.php Diese Funktion gibt die Anzahl der Bytes zurück, die in die Datei geschrieben wurden, oder FALSE bei einem Fehler. Nur wenn sich jemand wundert.
Meister James
7
@JerahmeelAcebuche Der zweite Prozess, bei dem versucht wird, die Sperre zu erlangen, "blockiert, bis die angeforderte Sperre erlangt wird" ( Quelle ). Mit anderen Worten, der zweite Prozess wartet, bis der erste die Datei geschlossen und die Sperre aufgehoben hat.
Rinogo
102

Verwenden Sie den aModus. Es steht für append.

$myfile = fopen("logs.txt", "a") or die("Unable to open file!");
$txt = "user id date";
fwrite($myfile, "\n". $txt);
fclose($myfile);
Valentin Mercier
quelle
Ich habe auch diese Ausgabe der \ n. es funktioniert nicht. funktioniert es für dich
Jerahmeel Acebuche
1
funktioniert das, wenn die Situation so ist, wie ich es gesagt habe?
Jerahmeel Acebuche
1
Das aFlag erstellt die Datei, wenn sie nicht vorhanden ist, und spielt unabhängig davon, ob Sie wirklich appendneuen Text verwenden. Für das \nfunktioniert es aber nur, wenn in doppelten Anführungszeichen "keine einfachen Anführungszeichen stehen'
Valentin Mercier
Ich meine die Situation, was passiert, wenn sich die beiden Benutzer in einem anderen Browser anmelden. dann öffnet der PHP die Datei in den beiden Browsern zur gleichen Zeit und aktualisiert sie auch zur gleichen Zeit. Wird es ein Problem geben? \
Jerahmeel Acebuche
1
Oh ja, es wird in diesem Fall eine SQL-Datenbank geben, die über eine integrierte Engine verfügt, um Rennbedingungen zu vermeiden. Aber das ist eine ganz neue Frage.
Valentin Mercier
10

Sie können es auf OO-Weise tun, nur eine Alternative und flexibel:

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;
    }

}

Verwenden Sie es dann folgendermaßen. Nehmen wir an, Sie haben user_namein einer Sitzung gespeichert (Semi-Pseudo-Code):

$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"]);
}

Überprüfen Sie Ihr Protokoll damit:

$log->getLog();

Ergebnis ist wie:

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


github.com/thielicious/Logger

Thielicious
quelle
1
Vielen Dank für diese Logger-Klasse! Ich hatte nicht erwartet, dass ich das finde, als ich diese Seite gefunden habe ... aber es ist tatsächlich die Grundlage für eine viel bessere Lösung als das, was ich ursprünglich implementieren wollte.
Myke Carter
4

Dies funktioniert für mich, indem ich Inhalte im selben Modus schreibe (auch erstelle) und / oder anhänge.

$fp = fopen("MyFile.txt", "a+") 
Mihir Bhatt
quelle
3

Versuchen Sie diesen Code:

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);
}

Ich benutze es immer so und es funktioniert ...

Rwakos
quelle
1
Es gibt keinen Grund dazu (!file_exists($logPath)) ? 'w':'a'- die aOption hat bereits das richtige Verhalten, wenn keine Datei vorhanden ist. Sie können diese Antwort also vereinfachen, indem Sie die Zeile entfernen $mode = ...;und die nächste Zeile in ändern $logfile = fopen($logPath, 'a');.
ToolmakerSteve
2

Es gibt keinen solchen Dateiöffnungsmodus wie "wr" in Ihrem Code:

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

Die Modi zum Öffnen von Dateien in PHP http://php.net/manual/en/function.fopen.php sind dieselben wie in C: http://www.cplusplus.com/reference/cstdio/fopen/

Es gibt die folgenden Hauptöffnungsmodi "r" zum Lesen, "w" zum Schreiben und "a" zum Anhängen, und Sie können sie nicht kombinieren. Sie können andere Modifikatoren wie "+" für die Aktualisierung und "b" für die Binärdatei hinzufügen. Der neue C-Standard fügt einen neuen Standard-Subspezifizierer ("x") hinzu, der von PHP unterstützt wird und an jeden "w" -Spezifizierer angehängt werden kann (um "wx", "wbx", "w + x" oder "w + bx" zu bilden "/" wb + x "). Dieser Subspezifizierer erzwingt, dass die Funktion fehlschlägt, wenn die Datei vorhanden ist, anstatt sie zu überschreiben.

Außerdem wurde in PHP 5.2.6 der Hauptöffnungsmodus 'c' hinzugefügt. Sie können 'c' nicht mit 'a', 'r', 'w' kombinieren. Das 'c' öffnet die Datei nur zum Schreiben. Wenn die Datei nicht vorhanden ist, wird sie erstellt. Wenn es existiert, wird es weder abgeschnitten (im Gegensatz zu 'w'), noch schlägt der Aufruf dieser Funktion fehl (wie dies bei 'x' der Fall ist). 'c +' Öffne die Datei zum Lesen und Schreiben. ansonsten hat es das gleiche Verhalten wie 'c'.

Zusätzlich und in PHP 7.1.2 wurde die Option 'e' hinzugefügt, die mit anderen Modi kombiniert werden kann. Es setzte das Close-on-Exec-Flag im geöffneten Dateideskriptor. Nur in PHP verfügbar, das auf POSIX.1-2008-konformen Systemen kompiliert wurde.

Für die Aufgabe, wie Sie sie beschrieben haben, wäre der beste Modus zum Öffnen von Dateien "a". Es öffnet die Datei nur zum Schreiben. Es platziert den Dateizeiger am Ende der Datei. Wenn die Datei nicht vorhanden ist, wird versucht, sie zu erstellen. In diesem Modus hat fseek () keine Auswirkung, Schreibvorgänge werden immer angehängt.

Folgendes benötigen Sie, wie oben bereits erwähnt:

fopen("logs.txt", "a") 
Maxim Masiutin
quelle
0

Obwohl es viele Möglichkeiten gibt, dies zu tun. Aber wenn Sie es auf einfache Weise tun und Text formatieren möchten, bevor Sie ihn in eine Protokolldatei schreiben. Hierfür können Sie eine Hilfsfunktion anlegen.

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);
    }
}
PHP Wurm ...
quelle