[PHP]pathinfo関数の使い方を徹底解説!ファイルパス操作の基本をマスター

PHP

PHPでファイルアップロード機能やファイル管理システムを開発する際、ファイルパスから情報を取得する必要が頻繁に発生します。この記事では、PHPのpathinfo関数について、実践的な使用例を交えながら詳しく解説していきます。

pathinfo関数とは?

pathinfoは、ファイルパスから様々な情報(ディレクトリ名、ファイル名、拡張子など)を抽出するための関数です。ファイル操作を行う際に非常に便利で、特にファイルアップロード処理やファイル名の検証で活躍します。

基本的な構文

mixed pathinfo(string $path, int $flags = PATHINFO_ALL)

パラメータ:

  • $path: 解析するファイルパス
  • $flags: 取得したい情報を指定(オプション)

戻り値:

  • $flagsを指定しない場合: 連想配列
  • $flagsを指定した場合: 文字列

pathinfoで取得できる情報

pathinfo関数は以下の4つの情報を取得できます。

キー説明フラグ定数
dirnameディレクトリパスPATHINFO_DIRNAME
basenameファイル名(拡張子含む)PATHINFO_BASENAME
extensionファイルの拡張子PATHINFO_EXTENSION
filenameファイル名(拡張子なし)PATHINFO_FILENAME

基本的な使い方

すべての情報を取得する

<?php
$path = '/var/www/html/uploads/profile_image.jpg';
$info = pathinfo($path);

print_r($info);
/*
Array
(
    [dirname] => /var/www/html/uploads
    [basename] => profile_image.jpg
    [extension] => jpg
    [filename] => profile_image
)
*/
?>

特定の情報だけを取得する

<?php
$path = '/var/www/html/documents/report.pdf';

// 拡張子だけを取得
$extension = pathinfo($path, PATHINFO_EXTENSION);
echo $extension; // 出力: pdf

// ファイル名(拡張子なし)だけを取得
$filename = pathinfo($path, PATHINFO_FILENAME);
echo $filename; // 出力: report

// ディレクトリパスだけを取得
$dirname = pathinfo($path, PATHINFO_DIRNAME);
echo $dirname; // 出力: /var/www/html/documents

// ファイル名(拡張子含む)だけを取得
$basename = pathinfo($path, PATHINFO_BASENAME);
echo $basename; // 出力: report.pdf
?>

実践的な使用例

1. ファイルアップロード時の拡張子チェック

<?php
// アップロードされたファイルの検証
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['uploaded_file'])) {
    $file = $_FILES['uploaded_file'];
    
    // 元のファイル名から拡張子を取得
    $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    
    // 許可する拡張子のリスト
    $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'pdf'];
    
    if (in_array($extension, $allowedExtensions)) {
        // ファイル名を生成(元のファイル名を使用)
        $originalFilename = pathinfo($file['name'], PATHINFO_FILENAME);
        $safeFilename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $originalFilename);
        $newFilename = $safeFilename . '_' . time() . '.' . $extension;
        
        $uploadPath = 'uploads/' . $newFilename;
        
        if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
            echo "ファイルのアップロードに成功しました: " . $newFilename;
        } else {
            echo "ファイルのアップロードに失敗しました";
        }
    } else {
        echo "許可されていないファイル形式です。許可されている形式: " . implode(', ', $allowedExtensions);
    }
}
?>

2. 画像ファイルのリサイズと保存

<?php
function resizeAndSaveImage($sourcePath, $destinationDir, $maxWidth = 800) {
    // パス情報を取得
    $pathInfo = pathinfo($sourcePath);
    $extension = strtolower($pathInfo['extension']);
    $filename = $pathInfo['filename'];
    
    // 画像ファイルかチェック
    $imageExtensions = ['jpg', 'jpeg', 'png', 'gif'];
    if (!in_array($extension, $imageExtensions)) {
        return false;
    }
    
    // 新しいファイル名を生成
    $newFilename = $filename . '_resized.' . $extension;
    $destinationPath = $destinationDir . '/' . $newFilename;
    
    // ここで実際のリサイズ処理を行う
    // (GDライブラリやImagickを使用)
    
    return $destinationPath;
}

$result = resizeAndSaveImage('uploads/photo.jpg', 'thumbnails');
?>

3. ファイル一覧の表示とフィルタリング

<?php
function listFilesByExtension($directory, $targetExtension) {
    $files = [];
    
    if (!is_dir($directory)) {
        return $files;
    }
    
    $items = scandir($directory);
    
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        
        $fullPath = $directory . '/' . $item;
        
        if (is_file($fullPath)) {
            $extension = pathinfo($fullPath, PATHINFO_EXTENSION);
            
            if (strtolower($extension) === strtolower($targetExtension)) {
                $files[] = [
                    'path' => $fullPath,
                    'name' => pathinfo($fullPath, PATHINFO_FILENAME),
                    'basename' => pathinfo($fullPath, PATHINFO_BASENAME),
                    'size' => filesize($fullPath)
                ];
            }
        }
    }
    
    return $files;
}

// PDFファイルだけを取得
$pdfFiles = listFilesByExtension('documents', 'pdf');

foreach ($pdfFiles as $file) {
    echo "ファイル名: {$file['basename']}<br>";
    echo "サイズ: " . number_format($file['size'] / 1024, 2) . " KB<br><br>";
}
?>

4. ファイル名の変更(拡張子を保持)

<?php
function renameFile($oldPath, $newName) {
    // 元のファイルのパス情報を取得
    $pathInfo = pathinfo($oldPath);
    $directory = $pathInfo['dirname'];
    $extension = $pathInfo['extension'];
    
    // 新しいファイルパスを生成
    $newPath = $directory . '/' . $newName . '.' . $extension;
    
    // ファイル名を変更
    if (rename($oldPath, $newPath)) {
        return $newPath;
    }
    
    return false;
}

// 使用例
$oldPath = 'uploads/temp_12345.jpg';
$newPath = renameFile($oldPath, 'profile_picture');
// 結果: uploads/profile_picture.jpg
?>

5. MIMEタイプの推測

<?php
function getMimeTypeFromExtension($filePath) {
    $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
    
    $mimeTypes = [
        'jpg'  => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'png'  => 'image/png',
        'gif'  => 'image/gif',
        'pdf'  => 'application/pdf',
        'doc'  => 'application/msword',
        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'xls'  => 'application/vnd.ms-excel',
        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'zip'  => 'application/zip',
        'txt'  => 'text/plain',
        'html' => 'text/html',
        'css'  => 'text/css',
        'js'   => 'application/javascript',
    ];
    
    return $mimeTypes[$extension] ?? 'application/octet-stream';
}

$filePath = 'documents/report.pdf';
$mimeType = getMimeTypeFromExtension($filePath);
echo $mimeType; // 出力: application/pdf
?>

よくある落とし穴と注意点

注意点1: 拡張子が複数あるファイル

<?php
$path = 'archive.tar.gz';
$extension = pathinfo($path, PATHINFO_EXTENSION);
echo $extension; // 出力: gz (gzだけが取得される)

$filename = pathinfo($path, PATHINFO_FILENAME);
echo $filename; // 出力: archive.tar

// 複数の拡張子を扱う場合は工夫が必要
function getFullExtension($filename) {
    $parts = explode('.', $filename);
    if (count($parts) > 1) {
        array_shift($parts); // 最初の要素(ファイル名本体)を除去
        return implode('.', $parts);
    }
    return '';
}

echo getFullExtension('archive.tar.gz'); // 出力: tar.gz
?>

注意点2: 拡張子がない場合

<?php
$path = '/usr/local/bin/composer';
$info = pathinfo($path);

print_r($info);
/*
Array
(
    [dirname] => /usr/local/bin
    [basename] => composer
    [filename] => composer
)
*/
// extensionキーが存在しない

// 安全に拡張子を取得する方法
$extension = pathinfo($path, PATHINFO_EXTENSION);
echo $extension; // 出力: (空文字列)

// または
$extension = isset($info['extension']) ? $info['extension'] : '';
?>

注意点3: パスの検証は行わない

<?php
// pathinfoは実際のファイルの存在をチェックしない
$path = '/non/existent/file.txt';
$info = pathinfo($path);

// ファイルが存在しなくても情報は取得できる
echo $info['extension']; // 出力: txt

// ファイルの存在確認が必要な場合は別途チェック
if (file_exists($path)) {
    $info = pathinfo($path);
    // 処理を続ける
} else {
    echo "ファイルが存在しません";
}
?>

注意点4: セキュリティ対策

<?php
// ❌ 危険: ユーザー入力をそのまま使用
$userFilename = $_POST['filename']; // 例: "../../config.php"
$path = 'uploads/' . $userFilename;

// ✅ 安全: パス情報を検証してから使用
$userFilename = $_POST['filename'];
$basename = pathinfo($userFilename, PATHINFO_BASENAME);
$path = 'uploads/' . $basename;

// さらに安全: 不正な文字を除去
$safeBasename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $basename);
$path = 'uploads/' . $safeBasename;
?>

関連する便利な関数

pathinfoと一緒によく使われる関数を紹介します。

<?php
$path = '/var/www/html/images/photo.jpg';

// basename: ファイル名を取得(pathinfoより簡単)
echo basename($path); // 出力: photo.jpg

// dirname: ディレクトリパスを取得
echo dirname($path); // 出力: /var/www/html/images

// realpath: 絶対パスを取得(実際のファイルが存在する必要あり)
echo realpath('images/../documents/file.txt');

// file_exists: ファイルの存在確認
if (file_exists($path)) {
    echo "ファイルが存在します";
}

// is_file: ファイルかどうかを確認
if (is_file($path)) {
    echo "これはファイルです";
}

// is_dir: ディレクトリかどうかを確認
if (is_dir('/var/www/html/images')) {
    echo "これはディレクトリです";
}
?>

パフォーマンスの考慮

pathinfoは非常に高速な関数ですが、大量のファイルを処理する場合は、必要な情報だけを取得することで若干の最適化が可能です。

<?php
// すべての情報を取得(わずかに遅い)
$info = pathinfo($path);
$extension = $info['extension'];

// 必要な情報だけを取得(わずかに速い)
$extension = pathinfo($path, PATHINFO_EXTENSION);

// ただし、複数の情報が必要な場合は一度に取得する方が効率的
$info = pathinfo($path);
$extension = $info['extension'];
$filename = $info['filename'];
$dirname = $info['dirname'];
?>

まとめ

pathinfo関数は、PHPでファイルパスを扱う際の必須ツールです。以下のポイントを押さえておきましょう。

  • ファイルパスから4種類の情報(dirname、basename、extension、filename)を取得できる
  • フラグを指定することで特定の情報だけを効率的に取得可能
  • ファイルアップロード処理での拡張子チェックに最適
  • 実際のファイルの存在確認は行わないため、必要に応じてfile_existsなどと組み合わせる
  • ユーザー入力を扱う際はセキュリティに注意
  • 複数の拡張子や拡張子なしのファイルには特別な対応が必要

この関数をマスターすることで、ファイル操作やアップロード機能の実装がずっと簡単になります。ぜひ実際のプロジェクトで活用してみてください!

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