is_dir

Tells whether a given path exists and is a directory.

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

Parameters

ParameterTypeDescription
$filenamestringPath to check. Relative paths are resolved against the current working directory. Symbolic links are followed before the check.

Return value

booltrue if the path exists and is a directory, 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_dir answers one question: does this path resolve to a directory that the current process can see? It follows symbolic links, so a link pointing at a folder returns true.

When to reach for it

Use it as a guard before scandir, opendir, rmdir or a recursive walk, and as the standard "create it if it isn't there" check:

if (!is_dir($path)) {
    mkdir($path, 0755, true);
}

Prefer it over file_exists when the distinction matters — file_exists returns true for a file sitting where you expected a folder, which is exactly the case that breaks the code further down.

What trips people up

The stat cache. Results are cached per request, so if you mkdir or rmdir a path and check it again in the same script — or if another process changes it — you can get a stale answer. Call clearstatcache() to force a fresh look.

Permissions, not existence. is_dir returns false when the parent directory lacks execute (+x) permission for the running user, even though the directory is really there. Under php-fpm that user is the pool user, not you.

It says nothing about access. A directory can exist and still be unreadable or unwritable; pair it with is_readable or is_writable before acting.

Note also that the mkdir-then-check pattern is racy across processes; check the return value of mkdir instead of trusting the gap between the two calls.

Example

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

When to use it

  • Create an upload or cache directory only if it is not already there.
  • Guard a recursive folder walk so a file passed by mistake does not blow up scandir().
  • Validate a user-supplied storage path in a CLI installer before writing to it.

Frequently asked questions

What is the difference between is_dir and file_exists?

file_exists returns true for anything at that path — file, directory or symlink target — while is_dir is true only for directories. Use is_dir when the path being a folder actually matters.

Does is_dir follow symbolic links?

Yes. A symlink pointing at a directory returns true, because the link is resolved before the check. Use is_link() first if you need to know that the path is itself a link.

Why does is_dir return false for a directory I can see?

Usually permissions: the PHP process user needs execute (+x) on every parent directory to stat the path, and under php-fpm that user is not your login. A stale stat cache entry is the other common cause.

More examples

Create the directory only if missing

The third argument to mkdir creates every missing parent, so one call builds all three levels. The is_dir guard stops mkdir emitting a warning on the second run, which is why this is the standard bootstrap idiom.

Example · php
<?php
$path = "storage/cache/tmp";

if (!is_dir($path)) {
    mkdir($path, 0755, true);
    echo "created\n";
} else {
    echo "already there\n";
}
var_dump(is_dir($path));

rmdir("storage/cache/tmp");
rmdir("storage/cache");
rmdir("storage");

Why file_exists is not enough

file_exists() cannot tell a file from a directory, so code that only checks it will happily continue and then fail inside scandir() or mkdir(). Checking is_dir() separately produces a clear error message instead.

Example · php
<?php
file_put_contents("logs", "oops, this is a file");

var_dump(file_exists("logs"));   // true
var_dump(is_dir("logs"));        // false

if (file_exists("logs") && !is_dir("logs")) {
    echo "path is taken by a regular file\n";
}
unlink("logs");

The stat cache can lie

The first call caches a negative result for that path. Depending on the platform the second call can repeat it even though the directory now exists; clearstatcache() discards the cache and gives the true answer. Long-running CLI scripts hit this constantly.

Example · php
<?php
$dir = "cache_probe";
var_dump(is_dir($dir));      // false, and now cached

mkdir($dir);
var_dump(is_dir($dir));      // may still be false
clearstatcache();
var_dump(is_dir($dir));      // true

rmdir($dir);

Discussion

  • Be the first to comment on this lesson.