概要
ファイルを扱う場面で常に付きまとうのが パス の問題。パスには 絶対パス (/Users/foo/data.txt のように / から始まる) と 相対パス (./data.txt のように現在地基準) があり、相対パスは 「どこから動かしているか」で結果が変わる ため事故りやすい。「スクリプトから見て隣のファイル」を確実に指すために PHP には __DIR__ (このファイルのディレクトリ絶対パス) と __FILE__ (このファイル自身) という定数がある。
パスは文字列なので、分解する関数群がある。dirname('/a/b/c.txt') で '/a/b'、basename(...) で 'c.txt'、pathinfo(...) で dirname / basename / filename / extension を 連想配列で一気に 取れる。拡張子を抜き出したい pathinfo($path, PATHINFO_EXTENSION) は頻出イディオム。絶対パスへ正規化したいなら realpath() がシンボリックリンクや .. を解決してくれる。
ディレクトリ内一覧は scandir($dir)。注意点は戻り値に必ず . (カレント)・.. (親) が混じる こと。array_diff($files, ['.', '..']) で除く定型処理。順序は OS 依存なので揃えたいなら sort($files) を明示する。__DIR__ / pathinfo / scandir の 3 点セット はファイル処理コードの「正しい型」。
学習目標
__DIR__/__FILE__の違いを言えるdirname/basename/pathinfoで パスを 分解 できるscandirでディレクトリ内のファイル一覧を取れる (./..の除外も含む)realpathで 絶対パスに正規化 できると知っている
ドリル
| # | 内容 |
|---|---|
01-path-info/ |
与えられたパス文字列を分解して各部分 (dir / basename / filename / extension) を出力 |
02-list-dir/ |
tests/data/sample/ 配下のファイル名一覧 (. .. を除く) をソートして出力 |
確認のコツ
pathinfoは 連想配列 (dirname/basename/filename/extension) を返すscandirの戻り値には.(カレント)・..(親) が必ず混ざる。array_diff($files, ['.', '..'])で除く- ファイル一覧を アルファベット順 で揃えたいなら
sort($files)を明示する (環境依存を消す)
📝 演習: ドリル 01 — `pathinfo` でパスを分解する
問題
以下のパス文字列を pathinfo で分解し、4 つの要素 (dirname / basename / filename / extension) を コロン + 半角スペース 区切りで 1 行ずつ出力してください。
$path = '/var/www/logs/access.2026-05-19.log';期待される出力:
dirname: /var/www/logs
basename: access.2026-05-19.log
filename: access.2026-05-19
extension: logヒント
$info = pathinfo($path);
echo "dirname: {$info['dirname']}\n";
echo "basename: {$info['basename']}\n";
echo "filename: {$info['filename']}\n";
echo "extension: {$info['extension']}\n";| キー | 中身 |
|---|---|
dirname |
ディレクトリ部分 (/var/www/logs) |
basename |
ファイル名 (拡張子付き) (access.2026-05-19.log) |
filename |
ファイル名 (拡張子なし) (access.2026-05-19) |
extension |
拡張子 (log — 先頭の . は付かない) |
つまづいたら
extensionが.log(先頭にドット) になる →pathinfoのextensionは.抜き で返す。自分で.を付けないことfilenameがaccess(途中まで) になる →pathinfoは 「最後の.より前」 をfilenameとする。仕様通りなのでこれが正解
📝 演習: ドリル 02 — `scandir` でディレクトリ一覧
問題
__DIR__ . '/tests/data/sample' 配下のファイル名を、. と .. を除いた 上で 昇順 にソートして 1 行ずつ出力してください。
tests/data/sample/ の中身 (このリポジトリにコミット済み):
apple.txt
banana.txt
cherry.txt
期待される出力:
apple.txt
banana.txt
cherry.txtヒント
$dir = __DIR__ . '/tests/data/sample';
$files = array_values(array_diff(scandir($dir), ['.', '..']));
sort($files);
foreach ($files as $f) {
echo $f . "\n";
}scandir($dir)はディレクトリ内のエントリ名を配列で返す- 戻り値には 必ず
.(カレント)・..(親) が含まれる のでarray_diffで除く array_valuesで キーを 0 から振り直す (array_diffは元のキーを保つため、後段のsort不要な順序ズレを防ぐ)sort($files)で 明示的に昇順 (PHP / OS 環境差を消す)
つまづいたら
- 出力の先頭に
...が混ざる →array_diff(scandir($dir), ['.', '..'])でカレント・親エントリを除く - 順序がバラバラ
→
sort($files)を明示的に呼ぶ。scandirのデフォルトは昇順だが、OS / ファイルシステム差で揺れることもある - 出力が 1 行に詰まる
→
echoの末尾に"\n"を付けるのを忘れている