はじめに
こんにちは!今回は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関数は便利ですが、大量のファイル名チェックを行う場合はパフォーマンスに注意が必要です。正規表現と比較すると:
- fnmatchはシンプルなワイルドカードパターンには最適
- 複雑なパターンには
preg_match()
の方が柔軟性が高い - 単純な文字列比較や
strpos()
が最も高速
まとめ
PHPのfnmatch()
関数は、ファイル名のパターンマッチングにおいて非常に便利なツールです。シェルスタイルのワイルドカードを使った直感的な構文で、ファイル名のフィルタリングやバリデーションが簡単に実装できます。
ファイル操作を多く扱うアプリケーションやCMSの開発において、この関数の活用方法を押さえておくことで、より効率的なコードが書けるようになるでしょう。
皆さんのコーディングライフが少しでも便利になれば幸いです!