Lab 10: File I/O

Objective

Read and write files with PHP's file functions, process CSV data, handle JSON files, work with streams, and use SPL file iterators for large file processing.

Background

PHP was built for web file processing — log parsing, CSV imports, config files, report generation. Its file functions (file_get_contents, fopen, fread) cover everything from simple text files to gigabyte log streams. Modern PHP also supports PHP streams (php://memory, php://stdin) for testing and pipeline processing.

Time

30 minutes

Prerequisites

  • Lab 05 (Functions)

Tools

  • PHP 8.3 CLI

  • Docker image: zchencow/innozverse-php:latest

  • All files written to /tmp/ for Docker compatibility


Lab Instructions

Step 1: Read & Write Text Files

💡 file_put_contents + file_get_contents are the fastest way for simple file reads/writes — one function call, no handle management. For large files (>10MB), use fopen/fread streams instead to avoid loading everything into memory.

📸 Verified Output:


Step 2: fopen Stream API

💡 feof() checks for end-of-file — loop with while (!feof($fh)) to read line by line. This is O(1) memory regardless of file size — only one line is in memory at a time. fgets($fh, 4096) reads up to 4096 bytes. Always fclose() after use to free the OS file handle.

📸 Verified Output:


Step 3: CSV Files

💡 fputcsv / fgetcsv handle CSV quoting and escaping automatically — fields containing commas, quotes, or newlines are properly wrapped in quotes. Never manually build CSV with implode(',', $row) — it breaks on fields with commas.

📸 Verified Output:


Step 4: JSON Files

💡 json_validate() (PHP 8.3) checks if a string is valid JSON without decoding it — much faster than json_decode() + error check for large payloads where you only need to validate. Always check json_last_error() after json_decode() — it silently returns null on failure.

📸 Verified Output:


Step 5: Directory Operations

💡 RecursiveIteratorIterator + RecursiveDirectoryIterator traverse directory trees without loading all paths into memory first. FilesystemIterator::SKIP_DOTS excludes . and .. entries. This is how Composer's autoloader scans your src/ directory for classes.

📸 Verified Output:


Step 6: PHP Streams & Memory Buffers

💡 php://memory is a virtual file handle backed by RAM — no disk I/O, no temp files. Use it for testing code that expects a file handle, or for building large strings incrementally. Output buffering (ob_start()) captures echo/print output — useful for template rendering and testing.

📸 Verified Output:


Step 7: Log File Parser

📸 Verified Output:


Step 8: Complete — Config File Manager

💡 Dot-notation config access (get('app.version')) is how Laravel's config() helper works — it splits the key on dots and traverses nested arrays. The array_reduce with reference traversal (&$ref) is the key technique for setting nested values without knowing the depth.

📸 Verified Output:


Verification

Summary

PHP's file I/O is comprehensive: text files, CSV, JSON, directories, streams, and buffers. You've built a full ConfigManager with dot-notation access — a pattern used in every major PHP framework. The stream API (php://memory, output buffering) enables zero-disk testing and template capture.

Further Reading

Last updated