PHP Tips | 文字列処理:URL・パス系 – ファイル名のみ取得

PHP PHP
スポンサーリンク

「ファイル名のみ取得」で何をしたいのかイメージする

まず、ゴールのイメージからはっきりさせます。

"/var/www/html/report/2025/sales.csv"      → "sales.csv"
"/var/www/html/report/2025/"              → ""(ファイル名なし)
"https://example.com/files/manual.pdf"    → "manual.pdf"
"https://example.com/files/download.php?file=abc" → "download.php"

やりたいことはこうです。

「フルパスや URL の文字列から、
最後の『ファイル名の部分』だけを取り出したい」

業務だと、ログに出すときに「ファイル名だけ見たい」、
ダウンロード画面で「保存ファイル名を表示したい」、
拡張子チェックと組み合わせて「アップロード可能な種類か判定したい」など、地味に出番が多い処理です。

ここを自前で explode('/') して最後の要素を取る、みたいに書き始めると、
URL とファイルパスの違い、末尾スラッシュの有無などで、すぐにバグります。
PHP には、これを一発でやってくれる便利な関数がちゃんとあります。


基本の主役:basename で「最後の要素」を取る

basename のイメージ

PHP には basename という関数があります。

string basename(string $path, ?string $suffix = null)
PHP

これは、

「パス文字列の最後の部分だけを返す」

関数です。

シンプルな例から見てみます。

echo basename('/var/www/html/report/2025/sales.csv'); // sales.csv
echo basename('C:\data\logs\app.log');                // app.log(Windows 風でもOK)
echo basename('manual.pdf');                          // manual.pdf
PHP

パスの区切り文字(/\)を見て、
一番最後の要素だけを返してくれます。

末尾にスラッシュがあるときの注意

ここが一つ重要ポイントです。

echo basename('/var/www/html/report/2025/'); // 2025
PHP

「ディレクトリ名の最後の部分」が返ってきます。
つまり、「ファイル名がないパス」でも、最後のディレクトリ名を返します。

「ファイル名があるかどうか」を判定したい場合は、
ここをちゃんと意識しておく必要があります。


URL からファイル名を取りたいときの考え方

URL も「パス部分」を取り出してから basename

URL 全体をそのまま basename に渡しても、
たいていは動きます。

echo basename('https://example.com/files/manual.pdf'); // manual.pdf
PHP

ただ、クエリやフラグメントが付いているときは注意が必要です。

echo basename('https://example.com/download.php?file=abc'); // download.php?file=abc
PHP

basename は「? より右側も含めて」最後の部分として扱ってしまいます。

なので、URL からファイル名を取りたいときは、

  1. parse_url で「パス部分」だけを取り出す
  2. そのパスに対して basename を使う

という二段構えにするのが安全です。

$url  = 'https://example.com/download.php?file=abc';
$path = parse_url($url, PHP_URL_PATH); // "/download.php"

echo basename($path); // download.php
PHP

これなら、クエリが付いていても正しくファイル名だけを取れます。


実務ユーティリティとして関数にまとめる

ファイルパス用:純粋に「最後の要素」を取る

まずは、ローカルファイルパス用のシンプルな関数から。

/**
 * ファイルパスから「ファイル名部分」を取得する
 * 末尾がディレクトリの場合は、そのディレクトリ名が返る
 */
function getFilenameFromPath(string $path): string
{
    return basename($path);
}
PHP

使い方のイメージです。

echo getFilenameFromPath('/var/www/html/report/2025/sales.csv'); // sales.csv
echo getFilenameFromPath('/var/www/html/report/2025/');          // 2025
PHP

「ディレクトリかファイルかは気にせず、とにかく最後の要素が欲しい」
という用途なら、これで十分です。

URL 用:パス部分だけを見てファイル名を取る

URL の場合は、さっきのように parse_url と組み合わせます。

/**
 * URL から「パスの最後の要素(ファイル名相当)」を取得する
 * パスがない場合は空文字
 */
function getFilenameFromUrl(string $url): string
{
    $path = parse_url($url, PHP_URL_PATH);

    if ($path === null || $path === false || $path === '') {
        return '';
    }

    return basename($path);
}
PHP

使い方の例です。

echo getFilenameFromUrl('https://example.com/files/manual.pdf');          // manual.pdf
echo getFilenameFromUrl('https://example.com/download.php?file=abc');    // download.php
echo getFilenameFromUrl('https://example.com/files/');                   // files
echo getFilenameFromUrl('https://example.com');                          // (空文字)
PHP

ここでのポイントは、「パスがない URL(ドメインだけ)」のときに、
空文字を返すようにしていることです。


「本当にファイル名か?」を判定したい場合の考え方

拡張子があるかどうかでざっくり判定する

業務でよくあるのは、

「最後の要素が『ディレクトリ名』ではなく『ファイル名』かどうか知りたい」

というニーズです。

完璧に判定するのは難しいですが、
実務では「拡張子があるかどうか」でざっくり判定することが多いです。

/**
 * パスまたは URL から「ファイル名(拡張子付き)」を取得する
 * 拡張子がなさそうな場合は空文字を返す
 */
function getFileLikeName(string $pathOrUrl): string
{
    // URL かどうかをざっくり判定して、パス部分だけ取り出す
    if (str_starts_with($pathOrUrl, 'http://') || str_starts_with($pathOrUrl, 'https://')) {
        $path = parse_url($pathOrUrl, PHP_URL_PATH) ?: '';
    } else {
        $path = $pathOrUrl;
    }

    $base = basename($path);

    // ドットを含まないなら「ファイルっぽくない」とみなす
    if (strpos($base, '.') === false) {
        return '';
    }

    return $base;
}
PHP

使い方の例です。

echo getFileLikeName('/var/www/html/report/2025/sales.csv');       // sales.csv
echo getFileLikeName('/var/www/html/report/2025/');               // (空文字)
echo getFileLikeName('https://example.com/files/manual.pdf');     // manual.pdf
echo getFileLikeName('https://example.com/files/');               // (空文字)
PHP

もちろん、「拡張子のないファイル」も世の中には存在しますが、
業務アプリで扱うファイル(CSV、PDF、画像、ZIP など)は、
ほとんどが拡張子付きなので、このくらいの割り切りで十分なことが多いです。


実務での使いどころのイメージ

ダウンロード画面で「保存ファイル名」を表示する

例えば、外部ストレージの URL をそのまま持っていて、
ユーザーには「このファイルをダウンロードします」と表示したいケース。

$url      = 'https://cdn.example.com/files/report_2025_final.pdf';
$filename = getFilenameFromUrl($url);

if ($filename === '') {
    $filename = 'download.dat'; // 予備の名前
}

echo "ダウンロードファイル:{$filename}";
PHP

ユーザーにとっては、長い URL よりも「ファイル名」が見えた方が安心です。

ログに「どのファイルがよくアクセスされているか」を出したい

アクセスログに URL が残っているとき、
「どのファイルがよくダウンロードされているか」を集計したいことがあります。

$url      = '/files/manual_v3.pdf?download=1';
$filename = getFilenameFromUrl('https://dummy' . $url);

// 集計用のキーとして $filename を使う
PHP

https://dummy のような適当なスキーム+ホストを付けてから parse_url させるテクニックは、
「パス+クエリだけ」の文字列を扱うときに便利です。


まとめ:今日からの「ファイル名のみ取得」ユーティリティ

大事なところだけ、ぎゅっとまとめます。

ファイルパスや URL から「最後の要素」を取りたいときは、basename を使う。
URL の場合は、parse_url($url, PHP_URL_PATH) でパス部分だけを取り出してから basename に渡す。
「本当にファイル名かどうか」をざっくり判定したいときは、「ドットを含むかどうか」で見るのが実務的。
ディレクトリかファイルかを厳密に判定するのではなく、「自分の用途に十分なルール」を決めておくのがポイント。

核になるコードは、この2つです。

function getFilenameFromPath(string $path): string
{
    return basename($path);
}

function getFilenameFromUrl(string $url): string
{
    $path = parse_url($url, PHP_URL_PATH);

    if ($path === null || $path === false || $path === '') {
        return '';
    }

    return basename($path);
}
PHP

もし、あなたのコードの中で「explode('/') して最後の要素を取っているところ」があれば、そこがこのユーティリティの差し替えポイントです。

タイトルとURLをコピーしました