こんにちは!今回はPHPのfile_exists関数について、実践的な使い方から注意点まで詳しく解説していきます。
基本的な使い方
file_exists関数は、ファイルやディレクトリが存在するかどうかを確認する関数です。戻り値はブール値(true/false)です。
$exists = file_exists('test.txt');
if ($exists) {
echo 'ファイルが存在します';
} else {
echo 'ファイルが存在しません';
}
詳細な使用例
1. ファイルとディレクトリの区別
function checkPath($path) {
if (!file_exists($path)) {
return 'パスが存在しません';
}
if (is_file($path)) {
return 'ファイルです';
}
if (is_dir($path)) {
return 'ディレクトリです';
}
}
2. アップロード前のファイル存在チェック
function saveUploadedFile($uploadedFile, $targetPath) {
// 同名ファイルの存在確認
if (file_exists($targetPath)) {
// ユニークなファイル名を生成
$info = pathinfo($targetPath);
$targetPath = $info['dirname'] . '/' .
$info['filename'] . '_' .
time() . '.' .
$info['extension'];
}
move_uploaded_file($uploadedFile['tmp_name'], $targetPath);
return $targetPath;
}
3. 設定ファイルのチェックと初期化
function initializeConfig($configPath) {
if (!file_exists($configPath)) {
// デフォルト設定を作成
$defaultConfig = [
'debug' => false,
'timezone' => 'Asia/Tokyo',
'database' => [
'host' => 'localhost',
'port' => 3306
]
];
file_put_contents(
$configPath,
json_encode($defaultConfig, JSON_PRETTY_PRINT)
);
}
return json_decode(file_get_contents($configPath), true);
}
重要な注意点
1. パーミッションの影響
// パーミッションによってはfile_existsがtrueを返しても
// 実際にはファイルにアクセスできない場合があります
if (file_exists($file)) {
if (!is_readable($file)) {
throw new Exception('ファイルは存在しますが、読み取り権限がありません');
}
if (!is_writable($file)) {
throw new Exception('ファイルは存在しますが、書き込み権限がありません');
}
}
2. レースコンディションの対策
function safeFileOperation($filename, callable $operation) {
// ファイルロックを使用して安全に操作
$handle = fopen($filename, 'r+');
if (!$handle) {
throw new Exception('ファイルを開けません');
}
try {
if (!flock($handle, LOCK_EX)) {
throw new Exception('ファイルをロックできません');
}
$result = $operation($handle);
flock($handle, LOCK_UN);
fclose($handle);
return $result;
} catch (Exception $e) {
if ($handle) {
flock($handle, LOCK_UN);
fclose($handle);
}
throw $e;
}
}
3. シンボリックリンクの扱い
function checkRealPath($path) {
if (!file_exists($path)) {
return 'パスが存在しません';
}
$realPath = realpath($path);
if (is_link($path)) {
return sprintf(
'シンボリックリンクです。実体は: %s',
$realPath
);
}
return sprintf('通常のパスです: %s', $realPath);
}
セキュリティ対策
パストラバーサル攻撃の防止
function secureFileExists($filename) {
// ファイル名を安全に処理
$filename = basename($filename);
$safePath = __DIR__ . '/allowed_directory/' . $filename;
// パスの正規化
$realPath = realpath($safePath);
if ($realPath === false) {
return false;
}
// 許可されたディレクトリ内かチェック
if (strpos($realPath, __DIR__ . '/allowed_directory/') !== 0) {
return false;
}
return file_exists($realPath);
}
パフォーマンスの考慮
file_exists関数は比較的軽量な関数ですが、大量のファイルチェックを行う場合は注意が必要です:
function optimizedBulkCheck($files) {
$results = [];
$cache = [];
foreach ($files as $file) {
$dir = dirname($file);
// ディレクトリの内容をキャッシュ
if (!isset($cache[$dir])) {
$cache[$dir] = scandir($dir);
}
$filename = basename($file);
$results[$file] = in_array($filename, $cache[$dir]);
}
return $results;
}
まとめ
file_exists関数は単純ですが、以下の点に注意して使用することが重要です:
- パーミッションの確認も併せて行う
- レースコンディションに注意する
- セキュリティ対策を忘れない
- 大量のファイルチェックの場合は最適化を考える
これらの点を意識することで、より安全で効率的なファイル操作が可能になります。