はじめに
PHPで正規表現による文字列置換を行う際、複数のパターンを処理したい場面はよくありますよね。従来はpreg_replace_callbackを何度も呼び出す必要がありましたが、PHP 7.0以降ではpreg_replace_callback_array関数を使うことで、複数のパターンとコールバック関数をまとめて処理できるようになりました。
この記事では、preg_replace_callback_arrayの基本から実践的な使い方まで、サンプルコードを交えながら詳しく解説します。
preg_replace_callback_arrayとは?
preg_replace_callback_arrayは、複数の正規表現パターンとそれぞれに対応するコールバック関数を配列で指定し、文字列置換を一度に実行できる関数です。
基本構文
preg_replace_callback_array(
array $pattern_callback_array,
string|array $subject,
int $limit = -1,
int &$count = null,
int $flags = 0
): string|array|null
パラメータ
- $pattern_callback_array: パターンとコールバック関数の連想配列
- $subject: 検索・置換対象の文字列(または配列)
- $limit: 各パターンの最大置換回数(デフォルト: -1=無制限)
- $count: 実行された置換の総数を格納する変数(参照渡し)
- $flags: オプションフラグ
基本的な使い方
シンプルな例
HTMLタグを一度に処理する例を見てみましょう。
<?php
$text = "こんにちは、<b>太字</b>と<i>斜体</i>のテキストです。";
$result = preg_replace_callback_array(
[
// <b>タグを**で囲む
'/<b>(.*?)<\/b>/' => function($matches) {
return '**' . $matches[1] . '**';
},
// <i>タグを__で囲む
'/<i>(.*?)<\/i>/' => function($matches) {
return '__' . $matches[1] . '__';
}
],
$text
);
echo $result;
// 出力: こんにちは、**太字**と__斜体__のテキストです。
?>
実践的な使用例
例1: マークダウン風のテキスト変換
<?php
$markdown = "見出しは #タイトル# で、リンクは [リンク文字](URL) で表現します。";
$html = preg_replace_callback_array(
[
// #見出し# → <h2>見出し</h2>
'/#(.*?)#/' => function($m) {
return '<h2>' . htmlspecialchars($m[1]) . '</h2>';
},
// [テキスト](URL) → <a href="URL">テキスト</a>
'/\[(.*?)\]\((.*?)\)/' => function($m) {
return '<a href="' . htmlspecialchars($m[2]) . '">'
. htmlspecialchars($m[1]) . '</a>';
}
],
$markdown
);
echo $html;
?>
例2: 個人情報のマスキング
<?php
$text = "電話: 090-1234-5678、メール: example@test.com";
$masked = preg_replace_callback_array(
[
// 電話番号をマスク
'/(\d{3})-(\d{4})-(\d{4})/' => function($m) {
return $m[1] . '-****-' . $m[3];
},
// メールアドレスをマスク
'/([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/' => function($m) {
return substr($m[1], 0, 2) . '***@' . $m[2];
}
],
$text
);
echo $masked;
// 出力: 電話: 090-****-5678、メール: ex***@test.com
?>
例3: 価格表示の整形
<?php
$text = "商品Aは1000円、商品Bは2500円、商品Cは10000円です。";
$formatted = preg_replace_callback_array(
[
// 4桁以上の数字をカンマ区切りに
'/(\d)(?=(\d{3})+(?!\d))/' => function($m) {
return $m[1] . ',';
},
// 数字+円を装飾
'/(\d[\d,]*)円/' => function($m) {
return '<span class="price">¥' . $m[1] . '</span>';
}
],
$text
);
echo $formatted;
// 出力: 商品Aは<span class="price">¥1,000</span>、...
?>
preg_replace_callbackとの違い
従来の方法(preg_replace_callback)
<?php
$text = "Hello World";
$text = preg_replace_callback('/Hello/', function($m) {
return 'Hi';
}, $text);
$text = preg_replace_callback('/World/', function($m) {
return 'PHP';
}, $text);
?>
preg_replace_callback_arrayを使った方法
<?php
$text = "Hello World";
$text = preg_replace_callback_array([
'/Hello/' => fn($m) => 'Hi',
'/World/' => fn($m) => 'PHP'
], $text);
?>
メリット:
- コードがスッキリして読みやすい
- パターンとコールバックの対応が明確
- パフォーマンスが若干向上(内部で最適化される)
置換回数の制限と確認
<?php
$text = "cat cat dog dog bird bird";
$result = preg_replace_callback_array(
[
'/cat/' => fn($m) => '猫',
'/dog/' => fn($m) => '犬',
'/bird/' => fn($m) => '鳥'
],
$text,
1, // 各パターンで最大1回まで置換
$count // 置換回数を取得
);
echo $result . "\n";
// 出力: 猫 cat 犬 dog 鳥 bird
echo "置換回数: {$count}回\n";
// 出力: 置換回数: 3回
?>
よくある使用例とパターン
URLの自動リンク化
<?php
function autoLink($text) {
return preg_replace_callback_array([
// HTTPSリンク
'/(https?:\/\/[^\s]+)/' => function($m) {
return '<a href="' . $m[1] . '" target="_blank">'
. $m[1] . '</a>';
},
// メールアドレス
'/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/' => function($m) {
return '<a href="mailto:' . $m[1] . '">' . $m[1] . '</a>';
}
], $text);
}
$text = "お問い合わせはinfo@example.comまで。詳細はhttps://example.comをご覧ください。";
echo autoLink($text);
?>
注意点とベストプラクティス
1. パターンの実行順序
配列の順序でパターンが適用されるため、順序が重要な場合は注意が必要です。
<?php
// 悪い例:先に広範なパターンを適用
$bad = preg_replace_callback_array([
'/\d+/' => fn($m) => '[数字]', // すべての数字
'/\d{3}-\d{4}/' => fn($m) => '[郵便番号]' // 届かない!
], '郵便番号は123-4567です');
// 良い例:具体的なパターンを先に
$good = preg_replace_callback_array([
'/\d{3}-\d{4}/' => fn($m) => '[郵便番号]', // 先に
'/\d+/' => fn($m) => '[数字]'
], '郵便番号は123-4567です');
?>
2. エスケープ処理
ユーザー入力を扱う場合は必ずエスケープを行いましょう。
<?php
$result = preg_replace_callback_array([
'/{{(.*?)}}/' => function($m) {
// XSS対策
return htmlspecialchars($m[1], ENT_QUOTES, 'UTF-8');
}
], $text);
?>
3. パフォーマンスの考慮
大量のテキスト処理では、不要な処理を避けましょう。
<?php
// 置換が必要かチェックしてから実行
if (preg_match('/<[^>]+>/', $text)) {
$text = preg_replace_callback_array([...], $text);
}
?>
まとめ
preg_replace_callback_arrayは、複数の正規表現パターンを効率的に処理できる強力な関数です。
主な特徴:
- ✅ 複数パターンを一度に処理できる
- ✅ コードの可読性が向上する
- ✅ PHP 7.0以降で使用可能
- ✅ 柔軟なコールバック処理が可能
複雑なテキスト処理を行う際は、ぜひこの関数を活用してみてください!
参考リンク
この記事が役に立ったら、ぜひシェアしてください!
