Ïðèãëàøàåì ïîñåòèòü
ßçûêîâ (yazykov.lit-info.ru)

Accessing Directories

Previous
Table of Contents
Next

Accessing Directories

Although we have shown briefly how to determine whether you have permissions to read from or write to a directory with functions such as is_readable and is_writeable, we have not covered exactly how to go about browsing the contents of said directory. Before we do this, however, we briefly discuss manipulating paths and filenames in PHP, because this can be frustrating at times.

Path Manipulation

One of the biggest problems we have to face when working with files as a web application author is that different operating system families have different methods for specifying file paths. Most notably, Windows tends to use the drive_letter:\path\to\file convention, whereas Unix systems use /path/to/file. However, we can do a few things to make this less stressful.

First, we can always use forward slashes. Windows is fully able to understand forward slashes, so we do not have to trouble ourselves with backslashes. This is doubly helpful when working with strings in code in PHP, because we have to be careful in double-quoted strings to escape the backslash to prevent PHP from trying to interpret it:

$path1 = 'c:\windows\php.ini';
$path2 = "c:\\windows\\php.ini";

// easier
$path  = 'c:/windows/php.ini';

Second, we can use functions provided by PHP to extract path information instead of trying to do this ourselves. PHP provides a number of very useful functions for this. The basename function takes a full path and returns the name of the file without path information included, whereas the dirname function returns the directory portion of the filename (without a trailing slash or backslash):

$path1 = 'c:/moo/goes/the/cow/milk.txt';

echo 'Filename: <b>' . basename($path1) . "</b><br/>\n";
echo 'Directory Name: <b>' . dirname($path1) . "</b><br/>\n";

The preceding code produces the following output:

Filename: milk.txt
Directory Name: c:/moo/goes/the/cow

The realpath function takes a potentially relative path and returns the actual absolute path represented by that file. The pathinfo extracts the directory name, base filename, and extension name for a given path, as follows:

$path2 = '../..//images/015/bunny.jpg';

echo "RealPath of <em>$path2</em>:  <b>" 
     . realpath($path2) . "</b><br/>\n";

print_r(pathinfo($path2)); echo "<br/>\n";
print_r(pathinfo(realpath($path2)));

This script produces the following output:

RealPath of ../..//images/015/bunny.jpg:
    D:\WebApps\WWW\images\bunny.jpg
Array ( [dirname] => ../../images
        [basename] => bunny.jpg
        [extension] => jpg )
Array ( [dirname] => D:\WebApps\WWW\images
        [basename] => bunny.jpg
        [extension] => jpg )

You should only use the pathinfo function on files that exist, of course. Otherwise, the output is of little use.

Using Classes to Browse Directory Contents

The viewing of the contents of a directory is most easily done in PHP5 with a pseudo-object-oriented class called dir, which behaves largely like a regular PHP class, except in the way it is created:

define('IMAGE_DIR', '/home/httpd/webapp/images');
$dir = dir(IMAGE_DIR);
if ($dir === FALSE)
  throw new NoSuchDirectoryException(IMAGE_DIR);

Note that we do not use the new keyword for this class. To browse the contents of the directory, we call the read method until it returns FALSE:

while (($entry = @$dir->read()) !== FALSE)
{
  echo $entry. "<br/>\n";
}

Note that we have to perform the explicit comparison !== instead of merely using !=. If we did not do this, and there was a directory entry named "0" (zero), the != operator would say it is equal to FALSE! With the !== operator, there is no chance for this confusion because it will verify that the value of $entry is typed as a Boolean.

Items returned by the dir class are in no particular order. (They are not sorted for us.) To go back to the beginning and start browsing through the contents again, we can call the rewind method on this class:

$dir->rewind();

Finally, when we are done with the dir object, we call the close method on it:

$dir->close();

Using Functions to Browse Directory Contents

Much existing PHP code that works with directories still uses the non-object-oriented methodology, which consists of a group of functions that correspond exactly to the member functions on the dir class shown previously.

You can open a directory by calling the opendir function, as follows:

$dir = opendir('c:/windows');
if ($dir === FALSE)
  throw new NoSuchDirectoryException('c:/windows');

You can read directory entries by using the readdir function:

while (($entry = @readdir($dir)) !== FALSE)
{
  echo $entry . "<br/>\n";
}

You can rewind the read pointer by using the rewinddir function:

rewinddir($dir);

Finally, you can close the read handle by calling the closedir function:

closedir($dir);

Changing the Current Directory

You can change the current working directory of PHP for the duration of the current executing script by calling the chdir function:

$result = @chdir('../logs');
if ($result === FALSE)
  throw new ChangeDirectoryException('../logs');

// cwd is now logs/ directory!

Creating and Removing Directories

Finally, you can create new and remove existing directories by using the mkdir and rmdir functions in PHP. You must have write permissions to the parent directory (so that the new directory entry can be written), and you cannot remove directories that are not empty. Both functions return FALSE on failure:

define('LOGDIR', 'logfiles');
$retval = @mkdir(LOGDIR);
if ($retval === FALSE)
  throw new MakeDirectoryException(LOGDIR);

$retval = @rmdir(LOGDIR);
if ($retval === FALSE)
  throw new RemoveDirectoryException(LOGDIR);


Previous
Table of Contents
Next