Kodokon kodokon.com

ไฟล์: อ่าน เขียน อัปโหลด JSON

อ่านและเขียนไฟล์ บันทึกเหตุการณ์ลงล็อก รับการอัปโหลดอย่างปลอดภัย และจัดเก็บข้อมูลของคุณในรูปแบบ JSON

10 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

การอ่านไฟล์ใช้ฟังก์ชันเพียงตัวเดียว file_get_contents() คืนเนื้อหาทั้งหมดในรูปสายอักขระ ส่วน file() แยกมันออกเป็นอาร์เรย์ของบรรทัด ก่อนอ่าน ให้ตรวจสอบการเข้าถึงด้วย is_readable() พาธที่ผิดจะคืนค่า false พร้อมกับคำเตือน

PHP
<?php

declare(strict_types=1);

$path = __DIR__ . '/notes.txt';

if (!is_readable($path)) {
    exit("File not found or unreadable.");
}

$content = (string) file_get_contents($path);
echo nl2br(htmlspecialchars($content, ENT_QUOTES));

$lines = file(
    $path,
    FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
);
echo count($lines) . " non-empty line(s)";
การอ่านไฟล์เดียวกันทั้งหมด แล้วอ่านทีละบรรทัด

สำหรับการเขียน file_put_contents() แทนที่เนื้อหาทั้งหมดโดยค่าเริ่มต้น มีสองแฟล็กที่เปลี่ยนพฤติกรรมนี้ FILE_APPEND เพิ่มต่อท้ายแทนการเขียนทับ ส่วน LOCK_EX ตั้งล็อกแบบเอกสิทธิ์ เพื่อไม่ให้สองคำขอที่เกิดขึ้นพร้อมกันเขียนปนกัน นั่นคือสูตรสำหรับล็อกของแอปพลิเคชันแบบเรียบง่าย

PHP
<?php

declare(strict_types=1);

$logFile = __DIR__ . '/app.log';

$line = sprintf(
    "[%s] New order from %s\n",
    date('Y-m-d H:i:s'),
    'alice@example.com'
);

file_put_contents(
    $logFile,
    $line,
    FILE_APPEND | LOCK_EX
);

echo "Event logged.";
ล็อกของแอปพลิเคชันที่เชื่อถือได้ในไม่กี่บรรทัด

การอัปโหลดไฟล์สมควรได้รับความใส่ใจเป็นพิเศษ แบบฟอร์มต้องประกาศ enctype="multipart/form-data" จากนั้น PHP จะอธิบายไฟล์ที่ได้รับไว้ใน $_FILES จงตรวจสอบ ทุกอย่าง ทั้งรหัสข้อผิดพลาด ขนาด และชนิดที่แท้จริงที่ตรวจพบด้วย finfo อย่าเชื่อนามสกุลไฟล์หรือชนิดที่เบราว์เซอร์แจ้งมาเด็ดขาด สุดท้าย ให้ใช้เพียง move_uploaded_file() เท่านั้นในการย้ายไฟล์ชั่วคราว

PHP
<?php

declare(strict_types=1);

$maxSize = 2 * 1024 * 1024;
$file = $_FILES['avatar'] ?? null;

if ($file === null || $file['error'] !== UPLOAD_ERR_OK) {
    exit("No valid file received.");
}

if ($file['size'] > $maxSize) {
    exit("File too large (2 MB max).");
}

$info = new finfo(FILEINFO_MIME_TYPE);
$mime = $info->file($file['tmp_name']);
$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png'];

if (!isset($allowed[$mime])) {
    exit("Format not allowed.");
}

$name = bin2hex(random_bytes(8));
$target = __DIR__ . '/uploads/' . $name
    . '.' . $allowed[$mime];

move_uploaded_file($file['tmp_name'], $target);
echo "Image saved.";
upload.php: ควบคุมขนาด ชนิดที่แท้จริง และชื่อไฟล์

รูปแบบ JSON คือสะพานเชื่อมตามธรรมชาติระหว่าง PHP กับส่วนที่เหลือของโลก json_encode() แปลงอาร์เรย์ให้เป็นสายอักขระ ส่วน json_decode() ทำในทางกลับกัน จงส่ง true เป็นอาร์กิวเมนต์ตัวที่สองเพื่อให้ได้อาร์เรย์แบบเชื่อมโยง และส่งแฟล็ก JSON_THROW_ON_ERROR เพื่อเปลี่ยน JSON ที่ผิดรูปให้กลายเป็นข้อยกเว้นที่ชัดเจน แทนที่จะได้ null เงียบ ๆ

PHP
<?php

declare(strict_types=1);

$path = __DIR__ . '/tasks.json';

$json = is_readable($path)
    ? (string) file_get_contents($path)
    : '[]';

$tasks = json_decode(
    $json,
    true,
    512,
    JSON_THROW_ON_ERROR
);

$tasks[] = [
    'title' => 'Review the lesson',
    'done' => false,
];

file_put_contents(
    $path,
    json_encode(
        $tasks,
        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
    ),
    LOCK_EX
);

echo count($tasks) . " task(s) saved";
คลังข้อมูลขนาดจิ๋ว: อ่าน แก้ไข เขียนใหม่

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. แฟล็ก FILE_APPEND ที่ส่งให้ file_put_contents() ทำหน้าที่อะไร?
    • มันเพิ่มเนื้อหาต่อท้ายไฟล์แทนการเขียนทับ
    • มันสร้างโฟลเดอร์แม่หากยังไม่มี
    • มันล็อกไฟล์ระหว่างการเขียน
  2. ทำไมจึงไม่ควรพึ่ง $_FILES['avatar']['type'] ในการตรวจสอบการอัปโหลด?
    • คีย์นี้มีอยู่เฉพาะบางเซิร์ฟเวอร์เท่านั้น
    • มันใช้ได้กับรูปภาพเท่านั้น
    • ค่านี้ถูกส่งมาจากเบราว์เซอร์และปลอมแปลงได้ คุณต้องตรวจหาชนิดที่แท้จริงด้วย finfo
  3. อาร์กิวเมนต์ตัวที่สอง true ใน json_decode($json, true) เปลี่ยนอะไร?
    • การถอดรหัสจะโยนข้อยกเว้นเมื่อเกิดข้อผิดพลาด
    • อ็อบเจกต์ JSON จะกลายเป็นอาร์เรย์แบบเชื่อมโยงของ PHP แทนที่จะเป็นอ็อบเจกต์ stdClass
    • คีย์จะถูกแปลงเป็นตัวพิมพ์ใหญ่