filemtime

Returns the Unix timestamp of when a file's contents were last modified.

Signature
filemtime(string $filename): int|false
  • Added in PHP 4.0.0

Parameters

ParameterTypeDescription
$filenamestringPath 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-Modified header.
  • 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

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

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.

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

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

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

  • Be the first to comment on this lesson.