สร้างหรือเขียน / ผนวกในไฟล์ข้อความ


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ทำงาน แต่ถ้าภายในเครื่องหมายคำพูดคู่"ไม่ใช่คำพูดเดียว'
Valentin Mercier

ฉันหมายถึงสถานการณ์ของสิ่งที่ถ้าผู้ใช้สองคนเข้าสู่ระบบในเบราว์เซอร์ที่แตกต่างกัน จากนั้น php จะเปิดไฟล์ในสองเบราว์เซอร์ในเวลาเดียวกันและอัปเดตในเวลาเดียวกันด้วย จะมีปัญหาหรือไม่ \
Jerahmeel Acebuche

1
โอ้ใช่แล้วจะมีในกรณีนี้ใช้ฐานข้อมูล SQL มีเอ็นจิ้นในตัวเพื่อหลีกเลี่ยงสภาพการแข่งขัน แต่นั่นเป็นคำถามใหม่ทั้งหมด
Valentin Mercier

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 นี้! ฉันไม่ได้คาดหวังว่าจะพบว่าเมื่อฉันพบหน้านี้ ... แต่จริงๆแล้วมันเป็นรากฐานของทางออกที่ดีกว่าที่ฉันวางแผนไว้ในตอนแรก
Myke Carter

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 ใหม่จะเพิ่ม subspecifier มาตรฐานใหม่ ("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' ที่สามารถใช้ร่วมกับโหมดอื่นได้ มันตั้งค่าสถานะ close-on-exec บน file descriptor ที่เปิด มีเฉพาะใน 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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.