Files
Learn how to work with files in PHP and how to avoid common file-related pitfalls.
It’s time to look at long-term data stores. The most obvious one is the file system. The logic is simple—if we need to save some data, we put it into a file. That’s what computers do.
Working with files isn’t popular in web applications, but it remains a powerful tool for storing data and passing it between applications.
Using files in PHP
PHP offers many functions for working with files. The complete list is in the PHP Manual.
Here’s a list of the most commonly used functions.
Single operation functions
These are useful when performing a single operation on a file.
- The
file_exists() function
returnstrue
if the requested file exists. If we want to read the file or write to it, it’s better to also check the permissions with theis_readable()
oris_writable() functions
. They returntrue
if the file exists and the script has the necessary permissions for them. - The
file_get_contents() function
reads the whole file into a string. - The
file()
function reads the whole file as an array of strings, one string per line. The result still contains line endings. - The
file_put_contents() function
saves a string into a file. By default, it overwrites the file. We can pass theFILE_APPEND
flag as a third argument to append the string to the end of the file instead. - The
readfile() function
passes the file contents to the output buffer. This is useful when we want to serve static files with PHP. For example, when we want to serve them only to logged-in users.
File handles
Functions with file handles are helpful when we want to perform multiple operations on the same file. We use them when we want to read or write the file in multiple steps, which, for example, we would do when working with data too big to keep in memory.
The file handle remembers the opened file and an internal pointer to a specific position in this file. Usually, we don’t need to think about it. The pointer updates in the background as we read or write through the file. We can also manipulate the pointer to read or write arbitrary parts of the file.
Here are the most commonly used functions with file handles:
- The
fopen() function
opens the file and returns the file handle to be used in other functions. The second parameter,$mode,
defines whether to open the file for reading, writing, or both. It also allows us to set whether we want to write to the beginning or end of the file. It determines how to behave when the file doesn’t exist. - The
fputs()
function writes a string into the file handle. - The
fgets()
function reads a string from the file handle. - The
fprintf()
function writes a formatted string into the file handle. It uses the same format specification asprintf()
. - The
fscanf()
function reads a formatted string from the file handle. It also uses the same format specification asprintf()
. This function is useful for reading the file and parsing its contents at the same time. - The
fclose()
function closes the file handle. It’s important to remember to call it because some writes might be buffered and changes won’t be saved if we don’t close the file. - The
fseek()
function moves the internal pointer to an arbitrary place in the file. - The
rewind()
function moves the pointer to the beginning of the file.
Protocols
PHP supports URL-like wrappers in the file path that assign a special logic to these resources. Some of the most interesting among these include the following:
- The
php://stdin
,php://stdout
, andphp://stderr
wrappers which will be used in console applications. - The
php://input
wrapper, which reads request bodies in web applications. Thephp://memory
andphp://temp
wrappers, which use in-memory and temporary files. These are good for tests. - The
data://
wrappers, which read data-URLs. This protocol allows us to encode data inside the URL instead of pointing at something. - The
phar://
wrapper, which works with Phar archives.
Locking files
By default, files are prone to the same concurrency issues as sessions. If two processes update the same file simultaneously, the results might be unpredictable.
Usually, it’s not a problem because applications tend to create new files instead of updating existing ones. But, if we need to work with a single file, PHP provides a solution for file-related concurrency issues in the form of a locking mechanism.
A PHP script can lock the file, so another PHP process won’t be able to change it until the first script finishes working with it. If a script tries to lock a file that’s already been locked by another process, it will wait until the lock is released and then lock it. This mechanism disallows concurrent access to the file, turning the file processing into a performance bottleneck. But, it also resolves concurrency issues.
We lock the file with the flock()
function. The first argument of this function is the file handle, and the second one is the lock mode. Here are the three supported lock modes:
LOCK_SH:
A shared read-only lock. Other processes can read the file but cannot modify it.LOCK_EX:
An exclusive lock. Other processes cannot read or modify the file. Good for updating the file.LOCK_UN:
An unlock mode that releases the previously set lock.
Also, we can add a non-blocking LOCK_NB
parameter. When it’s on, if another process currently locks the file, flock()
will return false
instead of waiting.
We can also release the lock by closing the file handle with fclose()
.
Example
We’re going to do the increasing counter again. This time, we store the value in a file. We lock the file before reading the value, so we don’t have concurrent updates. And, we’re using file handle functions because we lock, read, and write the same file.
Get hands-on with 1200+ tech skills courses.