[PHP]file_exists関数の完全ガイド – ファイルやディレクトリの存在確認方法を徹底解説!

PHP

こんにちは!今回は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関数は単純ですが、以下の点に注意して使用することが重要です:

  1. パーミッションの確認も併せて行う
  2. レースコンディションに注意する
  3. セキュリティ対策を忘れない
  4. 大量のファイルチェックの場合は最適化を考える

これらの点を意識することで、より安全で効率的なファイル操作が可能になります。

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