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などと組み合わせる - ユーザー入力を扱う際はセキュリティに注意
- 複数の拡張子や拡張子なしのファイルには特別な対応が必要
この関数をマスターすることで、ファイル操作やアップロード機能の実装がずっと簡単になります。ぜひ実際のプロジェクトで活用してみてください!
