PHP: `file_get_contents()`にディレクトリを指定すると`Permission denied`と表示される
ファイル内容を文字列に読み込む関数にディレクトリを指定したらエラーになるのは当然ですが、エラー文にPermission denied
と表示されるので混乱してしまいました。
<?php echo file_get_contents('foo-dir'); // エラー文 // Warning: file_get_contents(foo-dir): failed to open stream: Permission denied ?>
ちなみに、存在しないファイルを指定した場合はNo such file or directory
と表示されます。
<?php echo file_get_contents('foo-file.txt'); // エラー文 // Warning: file_get_contents(foo-file.txt): failed to open stream: No such file or directory ?>
実際に混乱した例
SimplePieという、有名なフィード取得ライブラリがあります。
ライブラリを一つのファイルにまとめる役割のbuild/compile.phpの54行目にfile_get_contents()
が使われています。
RecursiveDirectoryIteratorとRecursiveIteratorIteratorでディレクトリ内を丸ごと、ディレクトリとファイルの区別なく取得した結果をひとつずつfile_get_contents()
の引数に指定しているため、ここでエラーが発生します。
<?php // Add all the files in the SimplePie directory $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(SP_PATH . '/library/SimplePie')); foreach($files as $file_path => $info) { $contents = file_get_contents($file_path); $compiled .= remove_header($contents) . "\n"; } ?>
エラー文にPermission denied
と表示されるため、「OSがWindowsだから発生したのか?」「パスのセパレータをバックスラッシュ(\
)からスラッシュ(/
)に変更すべきなのか?」など試行錯誤を重ねて、ようやく原因に気づきました。
下記のようにすればディレクトリが引数に指定されるのを防げます。
<?php // Add all the files in the SimplePie directory $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(SP_PATH . '/library/SimplePie')); foreach($files as $file_path => $info) { // ファイルの場合のみ、file_get_contentsを実行 if (is_file($file_path)) { $contents = file_get_contents($file_path); $compiled .= remove_header($contents) . "\n"; } } ?>
GitHubでプルリクエストを送りました。
https://github.com/simplepie/simplepie/pull/419
ただ、なぜこんな単純なミスが長い間放置されていたのでしょうか?
SimplePieの最新版1.3.1は2012年10月31日に公開されいますが、当時のPHPでは問題なかったのでしょうか?
…ともかく、返信を待つことにします。