Tạo hoặc viết / nối vào tệp văn bản


170

Tôi có một trang web mà mỗi khi người dùng đăng nhập hoặc đăng xuất tôi sẽ lưu nó vào một tệp văn bản.

Mã của tôi không hoạt động trong việc nối thêm dữ liệu hoặc tạo tệp văn bản nếu nó không tồn tại .. Đây là mã mẫu

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

Có vẻ như nó không nối vào dòng tiếp theo sau khi tôi mở lại.

Ngoài ra tôi nghĩ rằng nó cũng sẽ có lỗi trong một tình huống khi 2 người dùng đăng nhập cùng một lúc, nó có ảnh hưởng đến việc mở tệp văn bản và lưu nó sau đó không?

Câu trả lời:


337

Hãy thử một cái gì đó như thế này:

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

5
Điều này có tạo ra một tệp văn bản nếu nó không tồn tại?
Jerahmeel Acebuche

5
Yup nó tạo tệp văn bản logs.txtvà nối thêm nội dung trong đó
SpencerX

5
tôi có một câu hỏi. sử dụng LOCK_EX. tôi biết rằng điều này sẽ ngăn chặn bất cứ ai khác viết vào tập tin cùng một lúc. Nhưng điều gì sẽ xảy ra với người khác?
Jerahmeel Acebuche

13
php.net/manual/en/feft.file-put-contents.php Hàm này trả về số byte được ghi vào tệp hoặc FALSE khi không thành công. Chỉ cần ai thắc mắc.
Master James

7
@JerahmeelAcebuche Quá trình thứ hai để cố gắng có được khóa "sẽ chặn cho đến khi khóa được yêu cầu" ( nguồn ). Nói cách khác, quy trình thứ hai sẽ đợi cho đến khi quy trình đầu tiên đóng tệp và phát hành khóa.
rinogo

102

Sử dụng achế độ. Nó là viết tắt của append.

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

tôi cũng có vấn đề này của \ n. nó không hoạt động. nó có hiệu quả với bạn không?
Jerahmeel Acebuche

1
Điều này có hoạt động nếu tình huống xảy ra như tôi đã nói?
Jerahmeel Acebuche

1
các acờ sẽ tạo ra các tập tin nếu nó không tồn tại và không có vấn đề gì sẽ đảm bảo rằng bạn thực sự appendmới văn bản. Đối với \nnó hoạt động nhưng chỉ khi bên trong dấu ngoặc kép "không trích dẫn đơn'
Valentin Mercier

ý tôi là tình huống sẽ thế nào nếu hai người dùng đăng nhập vào trình duyệt khác nhau. sau đó php sẽ mở tệp trên hai trình duyệt cùng một lúc và cập nhật nó cùng một lúc. sẽ có vấn đề chứ? \
Jerahmeel Acebuche

1
Ồ, vâng, trong trường hợp này sẽ sử dụng cơ sở dữ liệu SQL, nó có một công cụ tích hợp để tránh các điều kiện chủng tộc. Nhưng đó là một câu hỏi hoàn toàn mới.
Valentin Mercier

10

Bạn có thể làm theo cách OO, chỉ là một cách thay thế và linh hoạt:

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

}

Sau đó sử dụng nó như thế này .. giả sử bạn đã user_namelưu trữ trong một phiên (mã bán giả):

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

Kiểm tra nhật ký của bạn với điều này:

$log->getLog();

Kết quả giống như:

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


github.com/thielicy/Logger


1
Rất cám ơn cho lớp Logger này! Tôi đã không mong đợi để tìm thấy điều đó khi tôi tìm thấy trang này ... nhưng thực sự nó là nền tảng của một giải pháp tốt hơn nhiều so với những gì tôi dự định ban đầu thực hiện.
Myke Carter

4

Điều này đang làm việc cho tôi, Viết (cũng tạo) và / hoặc nối thêm nội dung trong cùng chế độ.

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

3

Hãy thử mã này:

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

Tôi luôn sử dụng nó như thế này và nó hoạt động ...


1
Không có lý do để làm (!file_exists($logPath)) ? 'w':'a'- atùy chọn đã có hành vi chính xác khi tệp không tồn tại. Vì vậy, có thể đơn giản hóa câu trả lời này bằng cách loại bỏ dòng $mode = ...;và thay đổi dòng tiếp theo thành $logfile = fopen($logPath, 'a');.
ToolmakerSteve

2

Không có chế độ mở tệp như "wr" trong mã của bạn:

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

Các chế độ mở tệp trong PHP http://php.net/manual/en/feft.fopen.php giống như trong C: http://www.cplusplus.com/reference/cstdio/fopen/

Có các chế độ mở chính sau "r" để đọc, "w" để ghi và "a" để chắp thêm và bạn không thể kết hợp chúng. Bạn có thể thêm các sửa đổi khác như "+" để cập nhật, "b" cho nhị phân. Tiêu chuẩn C mới thêm một bộ phân loại tiêu chuẩn mới ("x"), được PHP hỗ trợ, có thể được thêm vào bất kỳ trình xác định "w" nào (để tạo thành "wx", "wbx", "w + x" hoặc "w + bx "/" wb + x "). Bộ phân loại này buộc hàm bị lỗi nếu tệp tồn tại, thay vì ghi đè lên nó.

Ngoài ra, trong PHP 5.2.6, chế độ mở chính 'c' đã được thêm vào. Bạn không thể kết hợp 'c' với 'a', 'r', 'w'. 'C' mở tệp chỉ để viết. Nếu tập tin không tồn tại, nó được tạo ra. Nếu nó tồn tại, nó không bị cắt ngắn (trái ngược với 'w'), cũng như cuộc gọi đến chức năng này không thành công (như trường hợp với 'x'). 'c +' Mở tệp để đọc và viết; mặt khác, nó có hành vi tương tự như 'c'.

Ngoài ra, và trong PHP 7.1.2, tùy chọn 'e' đã được thêm vào có thể được kết hợp với các chế độ khác. Nó đặt cờ close-on-exec trên bộ mô tả tệp đã mở. Chỉ có sẵn trong PHP được biên dịch trên các hệ thống tuân thủ POSIX.1-2008.

Vì vậy, đối với tác vụ như bạn đã mô tả, chế độ mở tệp tốt nhất sẽ là 'a'. Nó mở tập tin chỉ để viết. Nó đặt con trỏ tập tin ở cuối tập tin. Nếu tập tin không tồn tại, nó sẽ cố gắng tạo nó. Trong chế độ này, fseek () không có hiệu lực, ghi luôn được thêm vào.

Đây là những gì bạn cần, như đã được chỉ ra ở trên:

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

0

Mặc dù có nhiều cách để làm điều này. Nhưng nếu bạn muốn làm điều đó một cách dễ dàng và muốn định dạng văn bản trước khi viết nó vào tệp nhật ký. Bạn có thể tạo một chức năng trợ giúp cho việc này.

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);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.