PHPのstat()関数のキャッシュ/キャッシュクリアに戸惑った
環境
PHP 7.013
stat()は内容をキャッシュします
stat()関数は内容をキャッシュします。下記のコードの2つのechoは同じatimeを出力します。
<?php touch('./touch.txt'); echo stat('./touch.txt')['atime'] . "\n"; sleep(2); touch('./touch.txt'); echo stat('./touch.txt')['atime'] . "\n";
公式ドキュメントにもその旨記載されています。
https://www.php.net/manual/ja/function.clearstatcache.php
statやlstat、 またはその他の関数(後述)を使用すると、PHPはパフォーマンス向上のために それらの関数の戻り値をキャッシュします。
キャッシュの削除にはclearstatcache()関数
キャッシュを明示的に削除したい場合はclearstatcache()関数を使用します。
とはいえtouch()でもキャッシュクリアしてほしいよね普通
もしもstat()が内容をキャッシュすることを知らなくとも、touch()関数を使用した場合はさすがにキャッシュをクリアしてほしいと思うはずです。
なぜならtouchコマンドってそういうものだからです。
結論から言いますと、touch()関数でstatのキャッシュはクリアされる場合とされない場合があります。
対象ファイルが'file://'で始まる場合、touch()関数はstatのキャッシュをクリアします。
冒頭のスニペットを書き換えると以下のようになります。(引用https://qiita.com/hnw/items/3af76d3d7ec2cf52fff8#comment-eacb1be2cf022d511900)
<?php $filename = 'file:///tmp/touch.txt'; touch($filename); echo stat($filename)['atime'] . "\n"; sleep(2); touch($filename); echo stat($filename)['atime'] . "\n";
参考文献URL一覧
https://www.php.net/manual/ja/function.stat.php
https://www.php.net/manual/ja/function.clearstatcache.php
PHPがstatシステムコールの結果をキャッシュしている件 - Qiita
https://github.com/php/php-src/blob/master/ext/standard/filestat.c#L660