is_file
Tells whether a given path exists and is a regular file.
is_file(string $filename): bool- Added in PHP 4
Parameters
| Parameter | Type | Description |
|---|---|---|
$filename | string | Path to check. Relative paths are resolved against the current working directory. Symbolic links are resolved and the target is checked. |
Return value
booltrue if the path exists and is a regular file, false otherwise.
Errors
Throws a ValueError if the path contains a null byte; emits E_WARNING when the path cannot be checked, for example under an open_basedir restriction.
is_file is true only for a regular file — not a directory, not a pipe, not a socket, not a device node. It follows symbolic links, so a link that points at a real file returns true.
When to reach for it
Prefer it over file_exists whenever the code that follows will open, read or include the path. file_exists('config') is true for a directory named config, and include or fopen then fails in a confusing way. is_file plus is_readable is the honest precondition for reading:
if (is_file($path) && is_readable($path)) {
$data = file_get_contents($path);
}It is also the right filter when walking a directory listing, since scandir mixes files and subdirectories together.
What trips people up
Broken symlinks return false. The link is resolved first, so a link whose target was deleted reports false from both is_file and file_exists, even though the link entry is still on disk. is_link is the only way to see it.
Results are cached. Create or delete a file and check it again in the same request and you may get the old answer until clearstatcache().
It is not a permission check. A file can exist and still be unreadable by the PHP user, and a missing execute bit on a parent directory makes is_file report false for a file that is really there.
Example
When to use it
- Filter a scandir() listing down to files before processing uploads.
- Check that a config or template path is a real file before include or file_get_contents.
- Decide between unlink() and rmdir() when cleaning up a path of unknown type.
Frequently asked questions
What is the difference between is_file and file_exists?
file_exists returns true for files and directories alike, while is_file is true only for regular files. Use is_file whenever the next step is to read, include or open the path.
Does is_file return true for a symlink?
It returns true if the symlink points at a regular file, because the link is resolved before the check. A symlink whose target is missing returns false; use is_link to detect the link itself.
Why does is_file return false for a file that exists?
Either the stat cache is holding an older result — call clearstatcache() — or the PHP user lacks execute permission on a parent directory, which prevents it from stat-ing the path at all.
More examples
Filtering a directory listing
scandir returns archive, a.txt and b.txt together; the is_file filter leaves only the two files. Note the check has to be done on the full path, because is_file resolves relative names against the working directory, not the directory you scanned.
<?php
mkdir("inbox");
mkdir("inbox/archive");
file_put_contents("inbox/a.txt", "1");
file_put_contents("inbox/b.txt", "2");
$entries = array_diff(scandir("inbox"), ['.', '..']);
$files = array_filter($entries, fn($e) => is_file("inbox/$e"));
print_r(array_values($files));
unlink("inbox/a.txt");
unlink("inbox/b.txt");
rmdir("inbox/archive");
rmdir("inbox");Safe read preconditions
The pair of checks covers both failure modes that file_exists() hides: a directory sitting at the path, and a file the PHP user cannot read. After unlink the same check correctly reports the file is gone.
<?php
$path = "settings.ini";
file_put_contents($path, "debug=1\n");
if (is_file($path) && is_readable($path)) {
echo "loading: ", trim(file_get_contents($path)), "\n";
} else {
echo "cannot load $path\n";
}
unlink($path);
echo is_file($path) ? "still here\n" : "gone\n";Choosing unlink or rmdir
unlink() fails on directories and rmdir() fails on files, so a cleanup routine has to branch on the type first. The output shows all three paths handled without a single warning.
<?php
function removePath(string $p): string {
if (is_file($p)) { unlink($p); return "unlinked file"; }
if (is_dir($p)) { rmdir($p); return "removed dir"; }
return "nothing to do";
}
file_put_contents("tmp.txt", "x");
mkdir("tmp_dir");
echo removePath("tmp.txt"), "\n";
echo removePath("tmp_dir"), "\n";
echo removePath("never_existed"), "\n";
Discussion