1. 導入
Webサイトのコンテンツにおいて、専門用語に解説ページへのリンクを自動的に付与する機能は、ユーザーの利便性を高め、サイトの回遊率を向上させるために非常に有効です。しかし、単純な置換処理を繰り返すと、「すでに置換されたHTMLタグ内の文字列」まで再度置換されてしまい、リンクが壊れるという問題が発生します。本稿では、この課題を解決し、実務で安全に利用できる実装手法を解説します。
2. 基礎知識
この処理の肝となるのは「文字列の置換」です。PHPには文字列置換関数として `str_replace` や `strtr` がありますが、これらを単純に使用すると、置換順序やマルチバイト文字の扱いで予期せぬ不具合が生じることがあります。
特に重要なのが「長い単語から先に置換する」というルールです。「ウェブ」と「ウェブブラウザ」という単語がある場合、「ウェブ」を先に置換してしまうと、「ウェブブラウザ」の「ウェブ」部分だけがリンク化され、意図しないHTML構造になってしまいます。これを防ぐために、置換対象リストを文字数の降順でソートする必要があります。
3. 実装/解決策
実務レベルでは、マルチバイト文字(UTF-8)を安全に扱うため、`preg_replace` を利用した正規表現による置換が最も堅牢です。正規表現を用いることで、HTMLタグ内を除外してテキストノードのみを置換するといった高度な制御も可能になりますが、まずはシンプルかつ安全な置換処理の例を紹介します。
4. サンプルプログラム
以下のコードは、文字数の長い順に単語をソートし、正規表現を用いて一括置換を行う実用的な実装例です。
/
function autoLinkKeywords($text, $wordlist) {
// 1. キーワードを文字数の長い順にソート(重要:部分一致の誤爆を防ぐ)
uksort($wordlist, function($a, $b) {
return mb_strlen($b, ‘UTF-8’) – mb_strlen($a, ‘UTF-8’);
});
// 2. 正規表現用にキーワードをエスケープし、OR条件で結合
$patterns = [];
$replacements = [];
foreach ($wordlist as $word => $url) {
// 正規表現の特殊文字をエスケープ
$escapedWord = preg_quote($word, ‘/’);
$patterns[] = ‘/’ . $escapedWord . ‘/u’;
$replacements[] = ‘‘ . $word . ‘‘;
}
// 3. 一括置換を実行
return preg_replace($patterns, $replacements, $text);
}
// 使用例
$content = “ウェブブラウザとはウェブサイトを閲覧するためのソフトウェアです”;
$keywords = [
“ウェブ” => “https://example.com/web”,
“ウェブブラウザ” => “https://example.com/browser”,
“ウェブサイト” => “https://example.com/site”,
“ソフトウェア” => “https://example.com/soft”
];
echo autoLinkKeywords($content, $keywords);
?>
5. 応用・注意点
■HTMLタグへの干渉を防ぐ
上記の単純置換では、もし元の文章に既にHTMLタグが含まれている場合、その中の属性名やタグ名まで置換されてしまうリスクがあります。より高度な実装を目指す場合は、`preg_replace_callback` を使用し、HTMLタグの中身かどうかを判定しながら置換するロジックを組むのがプロの現場での定石です。
■パフォーマンスの考慮
キーワード数が数千件を超える場合、毎回正規表現を生成して置換するとサーバー負荷が増大します。その場合は、キャッシュエンジン(RedisやMemcached)を利用して置換済みのHTMLを保存するか、キーワードの出現を事前に抽出する仕組みを検討してください。
■文字エンコーディング
PHPのマルチバイト関数を使用する際は、必ず `mb_internal_encoding(‘UTF-8’)` 等で文字コードを明示的に設定し、環境による挙動の違いを防ぐようにしてください。