在PHP开发中,有时我们需要调整文件的时间属性,例如让生成的新文件看起来像是更早之前创建的,或者在迁移文件时保留原有的时间信息。严格来说,PHP并没有一个跨平台且直接修改“文件创建日期”的标准函数,因为不同操作系统对文件时间的定义并不一致。理解这一点,是正确处理文件时间的前提。

文件时间的概念厘清
在类Unix系统中,每个文件通常维护三种时间:访问时间(atime)、修改时间(mtime)以及状态变更时间(ctime)。很多人误以为filectime返回的是创建时间,其实它返回的是文件元数据或内容最后一次发生改变的时间,例如权限修改也会更新ctime。真正的“创建时间”(birth time)在ext4等较新文件系统中才被支持,且PHP标准函数并未直接暴露读取和修改它的接口。
Windows系统下的NTFS则明确记录文件的创建时间、最后访问时间和最后写入时间。在Windows中,PHP的filectime往往对应创建时间,而filemtime对应写入时间。这种差异导致同一段PHP代码在不同平台表现不同,因此讨论“修改创建日期”必须先明确运行环境。
使用touch函数修改时间
touch是PHP中最常用的时间调整函数,它可以设置文件的访问时间和修改时间。虽然它不能直接修改Unix下的ctime或Windows下的创建时间,但在大多数业务场景中,将mtime和atime调整为指定值已经能满足“伪装文件日期”的需求。
下面的示例演示如何用touch将文件时间改为2022年1月1日:
<?php
$file = '/var/www/html/test.txt';
$targetTime = mktime(0, 0, 0, 1, 1, 2022); // 2022-01-01 00:00:00
if (touch($file, $targetTime, $targetTime)) {
echo '修改成功,当前mtime为:' . date('Y-m-d H:i:s', filemtime($file));
} else {
echo '修改失败,请检查文件权限';
}
?>
该方法的优点是纯PHP实现、无需系统命令、在共享虚拟主机中通常也可用。缺点是它无法触及Windows的创建时间,且在Unix中ctime会在touch调用时更新为当前时间,因此若严格依赖ctime判断文件新旧则会失效。
Windows下借助COM对象改创建时间
如果程序明确运行在Windows服务器,并且必须修改文件的创建日期,可以利用Windows的FileSystemObject通过COM扩展操作。这要求PHP开启com_dotnet扩展,且通常以管理员权限运行。
示例代码如下:
<?php
$file = 'C:\inetpub\wwwroot\test.txt';
$target = '2022-01-01 00:00:00';
try {
$fso = new COM('Scripting.FileSystemObject');
$objFile = $fso->GetFile($file);
// Windows下可设置DateCreated
$objFile->DateCreated = $target;
echo '创建时间已尝试修改为:' . $target;
} catch (Exception $e) {
echo '操作出错:' . $e->getMessage();
}
?>
这种方式确实能改变NTFS记录的创建时间,但局限性很明显:仅限Windows、依赖COM组件、在Linux或容器环境完全无效。此外部分杀毒软件会拦截脚本修改文件底层属性,导致稳定性问题。
复制重建法兼容多平台
一种折中方案是:读取原文件内容,创建新文件并先touch为目标时间,再写入内容。由于新文件在Windows下创建时间就是写入时的时间,此法则不适用改创建时间;但在Unix中,配合touch仍可控制mtime。它的核心价值在于避免直接修改原文件权限不足的问题。
代码示范:
<?php $src = '/data/old.txt'; $dst = '/data/new.txt'; $time = mktime(0, 0, 0, 1, 1, 2022); touch($dst, $time, $time); copy($src, $dst); // copy会更新mtime为复制时刻,需再次touch touch($dst, $time, $time); echo '新文件时间已同步'; ?>
该办法在备份同步工具中较常见,通过重建文件保证时间一致。缺点是若文件很大则耗时增加,且原文件的扩展属性可能丢失。实际项目中应根据文件系统类型选择方案,不要盲目追求修改创建时间。
方法对比与选型建议
为方便理解,将三种方式的核心差异整理如下:
| 方法 | 适用系统 | 能否改创建时间 | 复杂度 |
|---|---|---|---|
| touch函数 | 全平台 | 否(仅mtime/atime) | 低 |
| COM对象 | Windows | 能 | 中 |
| 复制重建 | 全平台 | 否 | 低 |
总体来看,若业务只要求文件“看起来修改于某天”,touch足够;若在Windows桌面应用中必须篡改创建日期,才考虑COM。在Linux生产环境,建议以mtime作为时间依据,避免陷入ctime与birth time的兼容性泥潭。