clearstatcache() 不会规范化路径。clearstatcache(true, "/a/b/c") 与 clearstatcache(true, "/a/b//c") 不同。
(PHP 4, PHP 5, PHP 7, PHP 8)
clearstatcache — 清除文件状态缓存
当您使用 stat()、lstat() 或下面列出的受影响函数中的任何一个时,PHP 会缓存这些函数返回的信息以提高性能。但是,在某些情况下,您可能希望清除缓存的信息。例如,如果在单个脚本中多次检查同一个文件,并且该文件在脚本操作期间有被删除或更改的风险,您可能选择清除状态缓存。在这种情况下,您可以使用 clearstatcache() 函数清除 PHP 缓存的关于文件的信息。
您还应该注意,PHP 不会缓存关于不存在的文件的信息。因此,如果您对一个不存在的文件调用 file_exists(),它将返回 false
,直到您创建该文件。如果您创建了该文件,即使您随后删除了该文件,它也会返回 true
。但是 unlink() 会自动清除缓存。
注意:
此函数缓存关于特定文件名的信息,因此您只需要在对同一个文件名执行多个操作并且需要关于该特定文件的未缓存信息时才调用 clearstatcache()。
受影响的函数包括 stat()、lstat()、file_exists()、is_writable()、is_readable()、is_executable()、is_file()、is_dir()、is_link()、filectime()、fileatime()、filemtime()、fileinode()、filegroup()、fileowner()、filesize()、filetype() 和 fileperms()。
clear_realpath_cache
是否也要清除 realpath 缓存。
filename
仅为特定文件名清除 realpath 缓存;仅在 clear_realpath_cache
为 true
时使用。
不返回值。
示例 #1 clearstatcache() 示例
<?php
$file = 'output_log.txt';
function get_owner($file)
{
$stat = stat($file);
$user = posix_getpwuid($stat['uid']);
return $user['name'];
}
$format = "UID @ %s: %s\n";
printf($format, date('r'), get_owner($file));
chown($file, 'ross');
printf($format, date('r'), get_owner($file));
clearstatcache();
printf($format, date('r'), get_owner($file));
?>
上面的示例将输出类似于以下内容
UID @ Sun, 12 Oct 2008 20:48:28 +0100: root UID @ Sun, 12 Oct 2008 20:48:28 +0100: root UID @ Sun, 12 Oct 2008 20:48:28 +0100: ross
clearstatcache() 不会规范化路径。clearstatcache(true, "/a/b/c") 与 clearstatcache(true, "/a/b//c") 不同。
未记录,但似乎 clearstatcache() 仅清除它被调用的进程的缓存。我有两个同时运行的 PHP 脚本,第一个脚本调用了 clearstatcache(),但第二个脚本仍然会死锁,除非我在其中也调用了 clearstatcache()
脚本 1
<?php
touch('system.lock');
...
unlink('system.lock');
clearstatcache(); // 应该由 unlink() 完成?
?>
脚本 2
<?php
while (is_file('system.lock') {
sleep(1);
clearstatcache(); // 没有它,脚本 2 将永远死锁!
}
?>
我还找到了这个页面,它得出了相同的结论
https://stackoverflow.com/questions/9251237/clearstatcache-include-path-sessions
如果您对远程文件执行 file_exists(),则 unlink() 不会清除缓存,例如
<?php
if (file_exists("ftp://ftp.example.com/somefile"))
?>
在这种情况下,即使您成功地执行了 unlink(),您也必须调用 clearstatcache()。
<?php
unlink("ftp://ftp.example.com/somefile");
clearstatcache();
?>
然后 file_exists() 正确地返回 false。
请注意,此函数仅影响文件元数据。但是,所有 PHP 文件系统函数都会对实际文件内容进行自己的缓存。如果您愿意,可以在 PHP.ini 中使用 "realpath_cache_size = 0" 指令禁用内容缓存。默认的内容缓存超时时间为 120 秒。
在开发工作和某些类型的应用程序中,内容缓存并不是一个好主意,因为您的代码可能会从您刚刚更改了内容的文件中读取旧数据。
注意:这与浏览器通常对所有 GET 请求(大多数 Web 访问)执行的缓存是分开的,除非 HTTP 标头覆盖它。它也与可选的 Apache 服务器缓存是分开的。
为了使这一点更加明显(以便搜索引擎更容易找到此内容)
如果您在 PHP 之外执行任何类型的文件操作(例如通过 system() 调用),您可能希望在对文件/目录/任何内容进行任何进一步测试之前清除状态缓存。例如
<?php
// is_dir() 强制执行状态调用,因此缓存已填充
if( is_dir($foo) ) {
system("rm -rf " . escapeshellarg($foo));
if( is_dir($foo) ) {
// ...仍然为真,即使 rm 成功,因为它只是
// 从缓存中读取,而不是重新运行 stat()
}
}
?>
在系统调用之后执行 clearstatcache(),一切都会好起来(除了由于清除状态缓存而导致的性能下降:-()。
在 Linux 上,分叉进程继承了父进程缓存的副本,但在分叉之后,这两个缓存不会互相影响。下面的代码片段演示了这一点,通过创建一个子进程并确认过时(缓存)的信息,然后清除缓存,并获取新信息。
<?php
function report($directory, $prefix = '') { printf('%sDoes %s exist? PHP says "%s"'. PHP_EOL, $prefix, $directory, is_dir($directory) ? 'yes' : 'no'); }
$target = './delete-me-before-running-statcache';
if (is_dir($target)) {
die("Delete $target before running.\n");
}
echo "Creating $target.\n";
mkdir($target) || die("Unable to create $target.\n");
report($target); // is_dir($target) 现在缓存为 true
echo "Unlinking $target.\n";
rmdir($target) || die("Unable to unlink $target.\n");
// 这将显示 "yes",这是旧的(不准确)信息。
report($target);
if (($pid = pcntl_fork()) === -1) { die("Failed to pcntl_fork.\n"); }
elseif ($pid === 0) {
// 子进程
report($target, '<<child>> ');
echo "<<child>> Clearing stat cache.\n";
clearstatcache();
report($target, '<<child>> ');
} else {
// 父进程
sleep(2); // 将其移至子进程块以反转测试。
report($target, '<<<parent>> ');
clearstatcache();
report($target, '<<<parent>> ');
}
?>