is_file

Tells whether a given path exists and is a regular file.

Signature
is_file(string $filename): bool
  • Added in PHP 4

Parameters

ParameterTypeDescription
$filenamestringPath 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.