Working with Files in PHP, Part 3

Welcome back. In my last article I introduced how to use PHP to read and write binary files. This week, I'll introduce the
concept of working with directories in PHP, including creating new directories,
changing directories, and getting a file list for a given directory using PHP's
pseudo directory object. We'll be starting from reading directories from a
list, and then we'll discuss creating new directories or changing the current
directory using PHP's directory manipulation functions. Let's get started.

The Directory Object

Working with directories in PHP is done through the use of a pre-defined
pseudo object built internally into PHP called dir. This object
has two member variables, $handle and $path, which
represent the handle to the directory (for use in other functions) and the
actual path of the directory (as a string). Along with these two variables, the
dir object also has three member functions, read(),
rewind(), and close().

Creating the Directory Object

Before we get into the specific member functions and their purposes, let's
first take a look at how to create a directory object. Like any other object in
PHP, instances are created with the new statement. In this case,
when creating dir, it also needs a single parameter, which
represents the directory being examined:

Now that our directory class is created, the instance ($mydir)
can be used in the same fashion as any other object. Our primary goal, of course,
is to list all the files in the provided directory, so we'll start there.

Reading Files from the Directory Object

With the dir object created, let's take a look at its primary method:
read(). This function reads one entry from the given directory at
every call and returns it as a string, or the boolean value false if there are
no more files to read. To use this function to read every file within a
directory, simply use it within a while loop as follows. (We assume
$mydir still exists.)

The above code fragment might look a bit strange, especially to the
beginner developer and warrants a little extra explanation. Within the while
statement above, a number of things are happening. First, we assign the result
of the read() method call to the variable $file.
Since that statement is enclosed within parenthesis, the value stored in
$file is then used in the comparison for the while statement.
Another oddity in the above fragment is the use of the !==
operator (not equals, except with an additional equal sign). It's not a typo.
This operator ensures that not only is a given value equal to (or in this case,
not equal to) another value, but that they are also of the same variable type.
Without this type of comparison, the while loop would end prematurely if a
directory (or filename) existed with the name of false. In plain English, we
read the current filename into $file, dropping out of the loop if
there are no more files to read.

With all of the files in the given directory now displayed, the directory
reference must be closed using the close() method. The entire
example is shown below:

You may have noticed that thus far we have not discussed any way of
re-reading the contents of a directory without creating a new instance of the
dir object. Thankfully, creating a new instance of the dir class is unnecessary.
That's what the rewind() method is for. When this method is
executed, the placeholder used to determine the next file in the directory
listing is reset to the beginning, allowing you to re-access the file list as
shown:

More Fun with Directories

Now that you know how to access the files within already existing
directories, let's take a look at how to create new directories, change into
existing ones, or determine if a given filename is a directory.

Determining If an Entry Is a Directory

In the examples I've shown you thus far, each entry returned from our
example $mydir object was labeled as Filename in the output.
Although acceptable for a simple demonstration, it is very likely (if not
certain) that some of the entries are subdirectories, not files. To
differentiate between the two, use the simple but useful function
is_dir(). This function takes a single parameter (an absolute or
relative pathname) and returns true if the path refers to a directory and false
if it refers to a file.

Note: In case you are unsure what the difference between an "absolute" and
"relative" pathname is, let me clarify. An absolute pathname is the complete
path to the desired directory or file starting from the root of the filesystem.
In UNIX-like systems, this would be something like
/complete/path/to/file. Conversely, a relative pathname starts
from the current directory (usually the same directory as the script being
executed) and would be something like ../path/to/file.

Notice that the complete path of the entry that we would like to check was
provided to the is_dir() function. Without this, none of the
entries would be processed properly since is_dir() would be
looking only in the current directory, not necessarily the directory being read
by $mydir object.

Changing the Current Directory

Of course, there are times when it would be useful to change the current
directory in order to perform file manipulations, etc. In order to accomplish
this, we'll use the PHP function chdir(). chdir()
function takes a single parameter, the directory to change to, and returns
either true or false indicating if PHP successfully changed into the desired
directory.

Creating and Removing Directories

The last thing we'll discuss today is the creation and removal of
directories from within PHP scripts. Both of these functions will only work
properly on UNIX-like systems in directories that have write access granted for
the user executing the PHP script (usually the Web server, i.e.
nobody). Next time, I'll discuss file permissions in detail. For
now just be aware of the limitation.

Creating a directory in PHP is done with the mkdir() function.
This function takes two parameters as shown below:

mkdir($dir_to_create, $permission_mask);

$dir_to_create represents the absolute or relative path of the
directory to create, and $permission_mask represents the
permissions to give that directory. Since permissions won't be covered in
detail until our next issue, we'll use 0777 (world-access) for our
permission level and will create our directory in /tmp/, which is always available to everyone. Beware that this means that anyone with access to the system can both read and write to the files and directories we create.

Note: Regardless of the operating system PHP is running on, a permission
mask is required in order for the function to work. Hence, if you are on a
system where the permissions do not apply (such as Windows), simply use
0777 as your permission mask.

Likewise, directories can be removed using the PHP rmdir()
function. This function takes a single parameter, the directory to remove, and
returns a boolean value indicating if the function call succeeded:

Stay Tuned

That's it for today. Although I have touched on a few topics, which you may
still be in the dark on (especially file permissions), don't worry. In my next
article, I'll discuss permissions in detail that should clear up any problems
that you might be having with them. Thanks for reading. See you next time.

John Coggeshall
is a a PHP consultant and author who started losing sleep over PHP around five years ago.