filemtime
Returns the Unix timestamp of when a file's contents were last modified.
filemtime(string $filename): int|false- Added in PHP 4.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$filename | string | Path to the file. |
Return value
int|falseThe last modification time as a Unix timestamp, or false on failure.
Errors
Emits an E_WARNING and returns false if the stat call fails, for example when the file does not exist.
filemtime answers the question "when did this file's content last change?" It is the most trustworthy of the three file timestamps, because it is updated by every write regardless of how the filesystem is mounted.
When to reach for it
- Cache invalidation. Rebuild a compiled template only when the source is newer than the compiled output.
- Cache busting. Append
?v=plus the mtime to an asset URL so browsers refetch on deploy. - HTTP conditional responses. Feed it into a
Last-Modifiedheader. - Finding files that changed since the last sync run.
What trips people up
PHP caches stat results per request. If your script writes a file and then reads its mtime, you may get the value from before the write. clearstatcache(true, $filename) fixes it, and this is by far the most common surprise with this function.
Resolution is one second on most filesystems, so two writes in the same second are indistinguishable. Any "has it changed?" check based purely on mtime can therefore miss a rapid second edit — combine it with filesize or a hash when correctness matters.
On failure you get false, and (int) false is 0, which date() renders as 1970. Check the file exists first.
Example
When to use it
- Recompile a Twig or Blade template only when the source file is newer than the cached one.
- Add ?v=filemtime() to CSS and JS URLs so browsers pick up new builds automatically.
- Emit a Last-Modified header and answer 304 Not Modified for unchanged static files.
Frequently asked questions
What is the difference between filemtime and filectime?
`filemtime` changes when the file's data is written, while `filectime` changes when the inode metadata changes — including permissions, ownership and renames. Use `filemtime` for cache invalidation; `filectime` also fires on a `chmod` that left the content untouched.
Why does filemtime return an old timestamp after I write the file?
PHP caches stat results for the duration of the request. Call `clearstatcache(true, $filename)` after writing and before reading the timestamp back.
Does filemtime work on directories?
Yes. For a directory it reports when an entry was last added, removed or renamed inside it — not when a file's contents deeper in the tree changed.
More examples
Rebuild only when the source is newer
The compiled file was backdated 60 seconds, so the source wins the comparison and the script prints `rebuilt` followed by the new contents. This two-timestamp comparison is the core of every file-based build cache.
<?php
file_put_contents('source.tpl', 'Hello {name}');
file_put_contents('compiled.php', '// stale build');
touch('compiled.php', time() - 60); // pretend it was built a minute ago
clearstatcache();
if (filemtime('source.tpl') > filemtime('compiled.php')) {
file_put_contents('compiled.php', '// rebuilt');
echo "rebuilt\n";
} else {
echo "cache still valid\n";
}
echo file_get_contents('compiled.php'), "\n";
unlink('source.tpl');
unlink('compiled.php');Cache-busting an asset URL
The two printed URLs carry different `v=` values, so a browser that cached the first one is forced to refetch. Note the `clearstatcache()` call — without it the second URL would repeat the first version number.
<?php
file_put_contents('app.css', 'body{margin:0}');
clearstatcache();
$url = '/assets/app.css?v=' . filemtime('app.css');
echo $url, "\n";
file_put_contents('app.css', 'body{margin:0;padding:0}');
touch('app.css', time() + 10);
clearstatcache(true, 'app.css');
echo '/assets/app.css?v=' . filemtime('app.css'), "\n";
unlink('app.css');Second-level resolution can hide a change
On a fast machine both writes land in the same second, so the timestamps usually match while the content clearly does not. When two edits can happen within a second, hash the contents instead of trusting mtime alone.
<?php
file_put_contents('fast.txt', 'aaa');
clearstatcache();
$a = filemtime('fast.txt');
file_put_contents('fast.txt', 'bbb'); // same second
clearstatcache();
$b = filemtime('fast.txt');
echo "timestamps identical: ", var_export($a === $b, true), "\n";
echo "content differs: ", var_export(md5('aaa') !== md5('bbb'), true), "\n";
unlink('fast.txt');
Discussion