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 returns true 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 the is_readable() or is_writable() functions. They return true 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 the FILE_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 as printf().
  • The fscanf() function reads a formatted string from the file handle. It also uses the same format specification as printf(). 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, and php://stderr wrappers which will be used in console applications.
  • The php://input wrapper, which reads request bodies in web applications. The php://memory and php://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.