is_writable
Checks whether a file or directory exists and can be written to by the current process.
is_writable(string $filename): bool- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$filename | string | Path to the file or directory being checked. |
Return value
booltrue if the path exists and is writable by the running process, false otherwise.
Errors
Does not throw. An open_basedir violation emits an E_WARNING; a missing path just returns false.
is_writable() reports whether the process running PHP could write to an existing path. The alias is_writeable() (with the extra e) is identical. For a file it means "could be opened for writing"; for a directory it means "new entries could be created inside it".
When to reach for it
The genuinely useful case is checking a directory before an install step, a cache warm-up, or an upload handler: is_writable('storage/logs') tells you whether the deployment permissions are right and lets you print an actionable error instead of a stack of warnings. Installers and CLI doctor commands are where it belongs.
What trips people up
It returns false for a path that does not exist yet, even when the containing directory would happily accept the new file. If your question is "can I create cache/data.json?", test is_writable(dirname($path)) when the file is absent. Beyond that, the check is advisory and racy: another process can revoke permission the instant after it returns true, and it cannot see ACLs, immutable flags, read-only mounts, or a full disk. If you are about to write anyway, just attempt the write and check the return value of file_put_contents().
Example
When to use it
- Fail an installer early with a clear message when storage/ or cache/ is not writable by the web server user.
- Decide at runtime whether to write a log file or fall back to error output.
- Verify an upload destination directory before accepting a large POST body.
Frequently asked questions
What is the difference between is_writable and is_writeable?
Nothing — is_writeable() is an alias kept for the common misspelling. Both accept the same argument and return the same value; is_writable() is the documented name.
Why does is_writable return false for a file I want to create?
Because the file does not exist yet, and is_writable() only reports on paths that do. Check the parent directory with is_writable(dirname($path)) instead.
Does is_writable guarantee my write will succeed?
No. It cannot see a full disk, a read-only mount, ACLs, filesystem quotas, or a permission change that happens a microsecond later. Always check the return value of the actual write.
More examples
The "can I create this path?" helper
The helper switches to the parent directory when the file is absent, which is what callers nearly always mean. The third case is false because the parent directory itself does not exist.
<?php
function canWrite(string $path): bool {
return file_exists($path) ? is_writable($path) : is_writable(dirname($path) ?: '.');
}
var_dump(canWrite('brand-new.txt')); // true
file_put_contents('exists.txt', 'x');
var_dump(canWrite('exists.txt')); // true
var_dump(canWrite('no/such/dir/x.txt')); // false
unlink('exists.txt');An install-time permissions report
Two directories pass and the non-existent one fails, so the script ends with "Not ready". Pairing is_dir() with is_writable() distinguishes "missing" from "present but locked" only if you report them separately.
<?php
foreach (['storage', 'cache'] as $d) { @mkdir($d); }
$required = ['storage', 'cache', 'read-only-imaginary'];
$ok = true;
foreach ($required as $dir) {
$good = is_dir($dir) && is_writable($dir);
$ok = $ok && $good;
printf("%-22s %s\n", $dir, $good ? 'OK' : 'FIX PERMISSIONS');
}
echo $ok ? "Ready\n" : "Not ready\n";
rmdir('storage'); rmdir('cache');Just try the write
The write either succeeds and reports its byte count or returns false, with no gap for permissions to change in between. In hot paths this is both faster and more correct than checking first.
<?php
$path = 'app.log';
$bytes = @file_put_contents($path, date('c') . " started\n", FILE_APPEND);
if ($bytes === false) {
echo "Logging disabled: cannot write $path\n";
} else {
echo "Wrote $bytes bytes\n";
echo file_get_contents($path);
}
unlink($path);
Discussion