PHP Tips | 文字列処理:URL・パス系 – 拡張子取得

PHP PHP
スポンサーリンク

「拡張子取得」で何をしたいのかイメージする

まず、ゴールをはっきりさせます。

"/var/www/html/report/sales.csv"          → "csv"
"/var/www/html/image/photo.jpeg"         → "jpeg"
"https://example.com/files/manual.pdf"   → "pdf"
"archive.tar.gz"                         → "gz"(どう扱うかは設計次第)
"README"                                 → ""(拡張子なし)

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

ファイルパスや URL の文字列から、「拡張子だけ」を安全に取り出したい。

業務だと、アップロードされたファイルの種類チェック、
ダウンロード時の Content-Type 判定、
ログ集計で「どの拡張子が多いか」を見る、などでよく使います。

ここを自前で explode('.') して最後を取る、みたいに書き始めると、
「ドットが複数あるファイル名」「拡張子なし」「URL にクエリ付き」などで、すぐに壊れます。
PHP には、これをかなり安全にやってくれる関数が用意されています。


基本の主役:pathinfo で拡張子を取る

pathinfo のイメージ

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

array pathinfo(string $path, int $flags = PATHINFO_ALL)
PHP

これは、

パス文字列を「ディレクトリ名」「ファイル名」「拡張子」などに分解してくれる関数

です。

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

$info = pathinfo('/var/www/html/report/sales.csv');

var_dump($info);
PHP

だいたいこんな配列になります。

array(4) {
  ["dirname"]   => "/var/www/html/report"
  ["basename"]  => "sales.csv"
  ["extension"] => "csv"
  ["filename"]  => "sales"
}
PHP

この中の extension が、まさに「拡張子」です。

拡張子だけを直接取り出す書き方

pathinfo は、第2引数にフラグを渡すと、
欲しい要素だけを直接返してくれます。

$ext = pathinfo('/var/www/html/report/sales.csv', PATHINFO_EXTENSION);

echo $ext; // csv
PHP

これが、一番シンプルで実務的な「拡張子取得」です。


URL から拡張子を取りたいときの考え方

URL 全体をそのまま pathinfo に渡すとどうなるか

実は、URL もそのまま pathinfo に渡せます。

$ext = pathinfo('https://example.com/files/manual.pdf', PATHINFO_EXTENSION);

echo $ext; // pdf
PHP

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

$ext = pathinfo('https://example.com/download.php?file=report.csv', PATHINFO_EXTENSION);

echo $ext; // ""(空文字)
PHP

pathinfo? より右側を「パスの一部」とは見なさないので、
download.php の拡張子 php は取れますが、
file=report.csvcsv は「URL の中のパラメータ」であって「パスの拡張子」ではありません。

つまり、

「URL のパス部分の拡張子」を取りたいのか
「URL の中のパラメータに含まれるファイル名の拡張子」を取りたいのか

で、やることが変わります。

パス部分の拡張子を取りたい場合

これはシンプルです。

/**
 * URL から「パス部分の拡張子」を取得する
 * 拡張子がなければ空文字
 */
function getExtensionFromUrlPath(string $url): string
{
    $path = parse_url($url, PHP_URL_PATH) ?: '';

    return pathinfo($path, PATHINFO_EXTENSION) ?? '';
}
PHP

使い方の例です。

echo getExtensionFromUrlPath('https://example.com/files/manual.pdf');      // pdf
echo getExtensionFromUrlPath('https://example.com/files/');               // ""
echo getExtensionFromUrlPath('https://example.com/download.php?file=abc'); // php
PHP

ここでは「パスの最後の要素の拡張子」を見ているだけです。


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

ファイルパス用:拡張子を小文字で返す

拡張子は、大文字小文字が混ざっていることがあります。

"photo.JPG" → "JPG"
"report.Pdf" → "Pdf"

比較や判定に使うなら、小文字にそろえておくと扱いやすいです。

/**
 * ファイルパスから拡張子を取得(小文字で返す)
 * 拡張子がなければ空文字
 */
function getExtensionFromPath(string $path): string
{
    $ext = pathinfo($path, PATHINFO_EXTENSION);

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

    return strtolower($ext);
}
PHP

使い方の例です。

echo getExtensionFromPath('/var/www/html/report/sales.csv'); // csv
echo getExtensionFromPath('/var/www/html/image/photo.JPG');  // jpg
echo getExtensionFromPath('/var/www/html/README');           // ""
PHP

これで、「JPG でも jpg でも同じ扱い」にできます。

URL 用:パス部分の拡張子を小文字で返す

さっきの URL 版も、小文字にそろえる形にしておくと便利です。

/**
 * URL から「パス部分の拡張子」を取得(小文字で返す)
 */
function getExtensionFromUrl(string $url): string
{
    $path = parse_url($url, PHP_URL_PATH) ?: '';

    $ext = pathinfo($path, PATHINFO_EXTENSION);

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

    return strtolower($ext);
}
PHP
echo getExtensionFromUrl('https://example.com/files/manual.PDF'); // pdf
echo getExtensionFromUrl('https://example.com/files/');           // ""
PHP

「複数ドット」のファイル名をどう扱うか

archive.tar.gz は「gz」か「tar.gz」か

pathinfo は、最後のドット以降を「拡張子」と見なします。

$info = pathinfo('archive.tar.gz');

var_dump($info['filename']);   // archive.tar
var_dump($info['extension']);  // gz
PHP

つまり、「拡張子は gz」という扱いです。

実務では、ここをどう扱うかは設計次第です。

  • 「とりあえず最後の拡張子だけ見れば十分」
    gz で OK
  • .tar.gz というセットで扱いたい」
    → 自前で少し工夫する

.tar.gz まで含めて取りたい場合の一例

簡易的に「よくある複合拡張子」を特別扱いする、という手もあります。

/**
 * よくある複合拡張子を考慮して拡張子を取得する
 * 例: archive.tar.gz → tar.gz
 */
function getSmartExtension(string $path): string
{
    $basename = basename($path);

    // よくある複合拡張子のパターン
    $multi = ['tar.gz', 'tar.bz2', 'tar.xz'];

    foreach ($multi as $ext) {
        if (str_ends_with($basename, '.' . $ext)) {
            return $ext;
        }
    }

    // 通常の拡張子
    $ext = pathinfo($basename, PATHINFO_EXTENSION);

    return $ext === null ? '' : strtolower($ext);
}
PHP
echo getSmartExtension('archive.tar.gz');   // tar.gz
echo getSmartExtension('backup.tar.bz2');   // tar.bz2
echo getSmartExtension('photo.jpg');        // jpg
PHP

「どこまでやるか」はプロジェクト次第ですが、
こういう「現実的な妥協」を入れることもあります。


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

アップロードされたファイルの種類チェック

典型的なのは、アップロードされたファイルの拡張子チェックです。

$filename = $_FILES['file']['name'] ?? '';

$ext = getExtensionFromPath($filename);

$allowed = ['jpg', 'jpeg', 'png', 'pdf'];

if (!in_array($ext, $allowed, true)) {
    // 許可されていない拡張子 → エラー
}
PHP

ここでのポイントは、

  • 「小文字にそろえた拡張子」で判定していること
  • 許可リストも小文字でそろえておくこと

です。

ログ集計で「どの拡張子が多いか」を見る

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

$url = '/files/manual_v3.pdf?download=1';

$ext = getExtensionFromUrl('https://dummy' . $url);

if ($ext !== '') {
    // $ext ごとにカウントする
}
PHP

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


まとめ:今日からの「拡張子取得」ユーティリティ

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

拡張子取得は、pathinfo($path, PATHINFO_EXTENSION) を使うのが基本。
URL の場合は、parse_url($url, PHP_URL_PATH) でパス部分だけを取り出してから pathinfo に渡す。
比較や判定に使うなら、拡張子は小文字にそろえておくと扱いやすい。
archive.tar.gz のような複合拡張子をどう扱うかは設計次第で、「最後の拡張子だけ見る」か「よくある複合拡張子を特別扱いする」かを決める。

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

function getExtensionFromPath(string $path): string
{
    $ext = pathinfo($path, PATHINFO_EXTENSION);
    return $ext === null ? '' : strtolower($ext);
}

function getExtensionFromUrl(string $url): string
{
    $path = parse_url($url, PHP_URL_PATH) ?: '';
    $ext  = pathinfo($path, PATHINFO_EXTENSION);
    return $ext === null ? '' : strtolower($ext);
}
PHP

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

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