指定したディレクトリのファイル一覧を取得する readdir() ですが、ファイル名を取得する while ループの条件判定で返り値が FALSE ではないことを、明確に調べなければなりません。「0(ゼロ)」や空文字を返す可能性があるということです。
実験
「target」というフォルダを作り、中に次のようなフォルダ・ファイルを作成します。
以下のソースコードを test.php で PHP が動作する環境に保存し、同じフォルダに先ほどの「target」フォルダを保存します。
1 2 3 4 5 6 7 8 9 10 | <?php $path = "target"; if ($handle = opendir($path)) { while ($entry = readdir($handle)) { echo "$entry\n"; } closedir($handle); } |
うまく動作しないです。これは、「0(ゼロ)」という名前のフォルダがあるためです。
while 文の判定式を PHP のマニュアルにあるように変更します。
1 2 3 4 5 6 7 8 9 10 | <?php $path = "target"; if ($handle = opendir($path)) { while (false !== ($entry = readdir($handle))) { echo "$entry\n"; } closedir($handle); } |
実行結果は次のとおり。
ちゃんと動作します。
言語のマニュアルや仕様書をよく読んでからソースコードを書かないと、こういうところがバグの原因になるんでしょうね。気をつけねばなりません。
応用
readdir() が返す値には「.」と「..」が含まれますが、これを取り除く場合が多いようです。先ほどのソースにこの処理を追加すると、
1 2 3 4 5 6 7 8 9 10 11 12 | <?php $path = "target"; if ($handle = opendir($path)) { while (false !== ($entry = readdir($handle))) { if ($entry !== '.' && $entry !== '..') { echo "$entry\n"; } } closedir($handle); } |
実行結果です。
更に、フォルダは除外したい場合は if 文にフォルダを除外する処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 | <?php $path = "target"; if ($handle = opendir($path)) { while (false !== ($entry = readdir($handle))) { if ($entry !== '.' && $entry !== '..' && !is_dir($path . "/" . $entry)) { echo "$entry\n"; } } closedir($handle); } |
実行結果です。
地味に間違う「!==」と「!=」
ファイル名を取得する while ループの条件判定は、値が等しいだけでなく型も等しいかを調べる厳密な比較 (===) であることに注意してください。今回の判定式の場合、「!==」である必要があります。次のソースコードを実行すると、
1 2 3 4 5 6 7 8 9 10 | <?php $path = "target"; if ($handle = opendir($path)) { while (false != ($entry = readdir($handle))) { echo "$entry\n"; } closedir($handle); } |
という予期しない結果になってしまいます。これは文字列と「TRUE」を緩やかに比較するとTRUEが返されるからだと思われます。詳しい話は「緩やかな比較 (==) と厳密な比較 (===) の違い | PHP プログラミング解説」にあります。
Comment