PHP Lessons - Lesson 2 - Working with files: opening, writing, reading.
In the previous lesson, we built the framework for our guestbook, blog, or chat application. Now it’s time to add functionality. In this lesson, we’ll save entries to files and display entries from those files.
PHP has many functions for file operations. We’ll look at a few of them. Most likely, your website will store data in a database (I’m sure of that) rather than in files. So we’ll just touch on the basics here to give you an understanding. We'll cover working with databases later.
If you don’t have the files from the last lesson, go back and download them first.
Let’s go to the add entry form:
/index.php?admin=1
This is the form we’ll use to add entries. To process the submitted entries, we need to check on index.php
whether the $_POST
variable has values. That’s done simply:
if ($_POST) { }
Easy, right? Now inside those curly braces, we’ll process the $_POST
array. But instead of writing the code directly there, we’ll move it into our class and call a method on the class object. In index.php
we call:
if ($_POST) { $obj->write($_POST); }
And in simpleCMS.php
we’ll define the write()
method:
public function write($p) { // message writing logic }
Why do we do this? To keep the code in index.php
clean and organized. index.php
is for control logic, while processing and display should go in other files like our simpleCMS
class. This separation makes the code easier to maintain, and if someone else looks at it, they’ll quickly understand what’s where. Even you will find it easier to navigate your own code this way.
Let’s start simple: print the $_POST
array passed from the form:
public function write($p) { print_r($p); }
Notice that we use the local variable $p
instead of directly referencing $_POST
. This allows the method to be more flexible — in the future, you might want to load entries from an XML file instead of a form. Using a parameter makes this method reusable.
When we fill out the form and submit it, I get something like:
Array ( [title] => Ivan [bodytext] => Hello, World! )
If your input was different, your array will be too. Now that we know the keys we’re working with — $p['title']
and $p['bodytext']
— we can save them to a file.
Writing to a file in PHP
Before we write to a file, we need to "open" it. Opening means linking the file to a PHP variable. All file work in PHP involves a variable of type resource
. Here’s how it works:
public function write($p) { $message = fopen("messages/file.txt", "w"); print_r($message); }
I created a file called file.txt
inside the messages
folder. When we fill out and submit the form, we get something like:
Resource id #4
Resource
is the type of variable $message
, and 4 is its internal ID. Once we have this, any action on $message
affects the file. We’ll write line by line so we can read line by line later:
public function write($p) { $message = fopen("messages/file.txt", "w"); fputs($message, $p['title'] . "\r\n"); fputs($message, $p['bodytext']); }
The \r\n
(inside double quotes!) means a newline. So the file will contain:
Ivan
Hello, World!
After writing, we should close the file to free up memory:
public function write($p) { $message = fopen("messages/file.txt", "w"); fputs($message, $p['title'] . "\r\n"); fputs($message, $p['bodytext']); fclose($message); }
You may notice that using w
overwrites the file each time. That's because of the second argument in fopen()
. Other options include:
- r – read only
- r+ – read and write
- w – write, overwriting existing content
- w+ – read/write and overwrite
- a – append
- a+ – read/append
Instead of overwriting, we can generate a unique filename using time()
:
public function write($p) { $message = fopen('messages/' . time(), "w"); fputs($message, $p['title'] . "\r\n"); fputs($message, $p['bodytext'] . "\r\n"); fputs($message, time()); fclose($message); }
This way, each file has a unique name based on the current timestamp. Now let’s read those files and display the entries.
Reading a file in PHP
To read a file, open it with fopen()
using the r
mode. All our files are in the messages
folder. We’ll use a while
loop and the opendir()
function to read all files:
if (is_dir('messages')) { if ($dh = opendir('messages')) { while (($file = readdir($dh)) !== false) { // process each file } closedir($dh); } }
File names are read with readdir()
and stored in $file
. Once done, close the directory with closedir()
.
Now let’s complete the display_public()
method:
public function display_public() { $content = ''; if (is_dir('messages')) { if ($dh = opendir('messages')) { while (($file = readdir($dh)) !== false) { if (substr($file, -4) == '.txt') { $filename = 'messages/' . $file; $message = fopen($filename, 'r'); $title = fgets($message); $body = fgets($message); $time = fgets($message); print ''; print '' . date('d-m-Y', $time) . ''; fclose($message); } } closedir($dh); } } $content .= ''; return $content; }' . $title . '
'; print '' . $body . '
'; print '
I’ve commented each line. If anything is unclear, just ask in the comments.
You likely won’t use line-by-line file reading in production, but it’s very useful for understanding PHP's file functions and how to work with folders and files.
Below you’ll find the source code for the intermediate version of the site.