Reading and writing whole files
For small files, two functions do everything. file_put_contents($path, $data) creates or overwrites a file and returns the number of bytes written; add FILE_APPEND to add to the end and LOCK_EX so two requests cannot interleave their writes. file_get_contents($path) returns the whole file as a string. file($path) returns an array of lines. All of them return false (plus a warning) on failure, so compare with === false — see Module 08.
<?php
$dir = sys_get_temp_dir() . '/hb-files-' . getmypid();
mkdir($dir);
$path = "$dir/notes.txt";
$bytes = file_put_contents($path, "first line\n");
echo "wrote $bytes bytes\n";
file_put_contents($path, "second line\nthird line\n", FILE_APPEND | LOCK_EX);
echo file_get_contents($path);
echo "size: ", filesize($path), " bytes\n";
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
echo count($lines), " lines, last = '", end($lines), "'\n";
var_dump(is_file($path), is_file("$dir/missing.txt"));
unlink($path); // delete the file
rmdir($dir); // delete the (now empty) directory
var_dump(file_exists($dir));wrote 11 bytes
first line
second line
third line
size: 34 bytes
3 lines, last = 'third line'
bool(true)
bool(false)
bool(false)sys_get_temp_dir() is the system temp folder; adding the process id keeps two runs from colliding. The program cleans up after itself.
Write a function countWords(string $path): int that reads a file and returns str_word_count of its contents. Test it on a file you create in the same program.
__DIR__ (the directory of the current file) instead: __DIR__ . '/data/users.json'. basename(), dirname() and pathinfo() split a path into its parts.<?php
$p = '/var/www/app/storage/reports/2026-sales.final.csv';
echo basename($p), "\n";
echo basename($p, '.csv'), "\n";
echo dirname($p), "\n";
echo dirname($p, 2), "\n"; // two levels up
print_r(pathinfo($p));2026-sales.final.csv
2026-sales.final
/var/www/app/storage/reports
/var/www/app/storage
Array
(
[dirname] => /var/www/app/storage/reports
[basename] => 2026-sales.final.csv
[extension] => csv
[filename] => 2026-sales.final
)