[PHP]fnmatch関数を完全マスター:パターンマッチングの実践的活用法と応用例

PHP

はじめに

こんにちは!今回はPHPの便利だけど意外と知られていない関数「fnmatch()」について詳しく解説します。ファイル名のパターンマッチングに使えるこの関数は、シンプルながら強力な機能を持っています。

fnmatch関数とは?

fnmatch()関数は、文字列がシェルのワイルドカードパターンに一致するかどうかを確認する関数です。その基本構文は次のとおりです:

bool fnmatch(string $pattern, string $string, int $flags = 0)

引数の説明

  • $pattern: 照合パターン(ワイルドカード記号を含む)
  • $string: チェックする対象の文字列
  • $flags: オプションのフラグ(後述)

戻り値

  • true: パターンに一致した場合
  • false: パターンに一致しなかった場合

fnmatchで使用できるワイルドカード

fnmatch関数では、以下のワイルドカードパターンが使えます:

  • *: 0文字以上の任意の文字列に一致
  • ?: 任意の1文字に一致
  • [abc]: 角括弧内の任意の1文字に一致
  • [a-z]: 指定範囲内の任意の1文字に一致
  • [!abc]または[^abc]: 角括弧内の文字以外の任意の1文字に一致

実践的な使用例

基本的な使い方

<?php
// 拡張子が.phpのファイルにマッチするか確認
$isPhpFile = fnmatch("*.php", "script.php");
echo $isPhpFile ? "PHPファイルです" : "PHPファイルではありません";
// 出力: PHPファイルです

// 特定のプレフィックスを持つファイルをチェック
$hasPrefix = fnmatch("config_*", "config_database.php");
echo $hasPrefix ? "設定ファイルです" : "設定ファイルではありません";
// 出力: 設定ファイルです
?>

複数のパターンを組み合わせる

<?php
// 画像ファイルかどうかをチェック
function isImageFile($filename) {
    return fnmatch("*.{jpg,jpeg,png,gif}", $filename, FNM_CASEFOLD);
}

echo isImageFile("photo.JPG") ? "画像ファイルです" : "画像ファイルではありません";
// 出力: 画像ファイルです
?>

フラグオプションの活用

fnmatch関数は第3引数に以下のフラグを指定できます:

  • FNM_NOESCAPE: バックスラッシュをエスケープ文字として扱わない
  • FNM_PATHNAME: スラッシュはワイルドカード「*」と「?」に一致しない
  • FNM_PERIOD: 先頭のドットは明示的に指定しない限りワイルドカードに一致しない
  • FNM_CASEFOLD: 大文字小文字を区別せずにマッチング
<?php
// 大文字小文字を区別しないマッチング
$caseInsensitive = fnmatch("*.txt", "README.TXT", FNM_CASEFOLD);
echo $caseInsensitive ? "一致します" : "一致しません";
// 出力: 一致します

// ディレクトリ構造を考慮したマッチング
$pathMatch = fnmatch("test/*.txt", "test/note.txt", FNM_PATHNAME);
echo $pathMatch ? "パスが一致します" : "パスが一致しません";
// 出力: パスが一致します
?>

fnmatchとglobの違い

混同されがちなglob()fnmatch()の違いを理解しましょう:

  • glob(): 実際のファイルシステムからパターンに一致するファイルを検索し、配列を返す
  • fnmatch(): ファイルシステムにアクセスせず、純粋に文字列パターンマッチングを行う
<?php
// glob()の例: 実際のファイルを検索
$phpFiles = glob("*.php");
print_r($phpFiles); // 現在のディレクトリの全PHPファイルを配列で返す

// fnmatch()の例: 文字列パターンのみをチェック
$isMatch = fnmatch("*.php", "index.php");
echo $isMatch ? "マッチします" : "マッチしません";
?>

実用的なシナリオ

ファイルアップロードの検証

<?php
function isAllowedFileType($filename) {
    // 許可されたファイル形式
    return fnmatch("*.{doc,docx,pdf,txt}", $filename, FNM_CASEFOLD);
}

$uploadedFile = "report.PDF";
if (isAllowedFileType($uploadedFile)) {
    echo "アップロード可能なファイル形式です";
} else {
    echo "許可されていないファイル形式です";
}
// 出力: アップロード可能なファイル形式です
?>

複数条件での設定ファイルの読み込み

<?php
function loadConfigFiles($directory) {
    $configs = [];
    $files = scandir($directory);

    foreach ($files as $file) {
        if (fnmatch("config_*.php", $file)) {
            // 設定ファイルを読み込む処理
            $configs[] = include "$directory/$file";
        }
    }

    return $configs;
}
?>

パフォーマンスに関する注意点

fnmatch関数は便利ですが、大量のファイル名チェックを行う場合はパフォーマンスに注意が必要です。正規表現と比較すると:

  1. fnmatchはシンプルなワイルドカードパターンには最適
  2. 複雑なパターンにはpreg_match()の方が柔軟性が高い
  3. 単純な文字列比較やstrpos()が最も高速

まとめ

PHPのfnmatch()関数は、ファイル名のパターンマッチングにおいて非常に便利なツールです。シェルスタイルのワイルドカードを使った直感的な構文で、ファイル名のフィルタリングやバリデーションが簡単に実装できます。

ファイル操作を多く扱うアプリケーションやCMSの開発において、この関数の活用方法を押さえておくことで、より効率的なコードが書けるようになるでしょう。

皆さんのコーディングライフが少しでも便利になれば幸いです!

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