WordPressの固定ページ内で<script>
タグを使用する際、ショートコードが正しく展開されないという問題に遭遇することがあります。この記事では、この問題の解決方法とレンタルサーバーに依存しない安全な実装方法を解説します。
問題の例
例えば、以下のようなショートコードを設定していたとします:
//shortcodes.php または functions.php
$urls = array(
'topthemeurl' => 'https://example.com/wp-content/themes/your-theme',
'commonsurl' => 'https://example.com/wp-content/themes/your-theme/commons'
);
function register_shortcodes() {
global $urls;
foreach ($urls as $key => $value) {
add_shortcode($key, function () use ($value) {
return $value;
});
}
}
固定ページ内で以下のように記述した場合:
<link rel="preload" href="[topthemeurl]/js/script.js" as="script">
<script src="[topthemeurl]/js/script.js"></script>
<link>
タグではショートコードが正しく展開されますが、<script>
タグでは展開されないという問題が発生します:
<!-- 結果(view-source) -->
<link rel="preload" href="https://example.com/wp-content/themes/your-theme/js/script.js" as="script">
<script src="[topthemeurl]/js/script.js"></script>
解決方法1: DOMDocument を使用する方法
この問題を解決するには、functions.php
に以下のコードを追加します:
//scriptタグ内のショートコードを処理する
add_filter('the_content', 'process_shortcodes_in_script', 99);
function process_shortcodes_in_script($content) {
if (false === strpos($content, '<script')) {
return $content;
}
//DOMDocumentを使用してHTMLを解析
$dom = new DOMDocument();
//HTML5のタグを適切に処理するための設定
libxml_use_internal_errors(true);
$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
//scriptタグを検索
$scripts = $dom->getElementsByTagName('script');
//各scriptタグに対して処理
foreach ($scripts as $script) {
//src属性を取得
$src = $script->getAttribute('src');
if ($src) {
//src属性内のショートコードを処理
$new_src = do_shortcode($src);
$script->setAttribute('src', $new_src);
}
}
//変更を適用したHTMLを返す
$new_content = $dom->saveHTML();
//余分なタグを削除
$new_content = preg_replace('/<(!DOCTYPE|html|body).*?>|<\/(html|body)>/', '', $new_content);
return $new_content;
}
注意点: この方法は一部のレンタルサーバー(カラフルボックスなど)では動作しますが、エックスサーバーやヘテムルなどの一部のサーバーでは、エラー処理が厳格なため動作しない場合があります。
解決方法2: 正規表現を使用する方法(サーバー互換性向上版)
より多くのレンタルサーバーで安定して動作する改良版コードを紹介します。この方法では、DOMDocumentではなく正規表現を使用しています:
/* ページ内の<script>タグでもショートコードを処理できるようにする */
function process_shortcodes_in_script($content) {
//高速チェック - scriptタグが無ければ処理しない
if (false === strpos($content, '<script')) {
return $content;
}
//正規表現を使用してscriptタグのsrc属性を見つけてショートコードを処理
$pattern = '/<script\s+[^>]*?src=(["\'])([^"\']*)\1[^>]*>/i';
return preg_replace_callback($pattern, function($matches) {
$src = $matches[2];
//ショートコードがある場合のみ処理
if (strpos($src, '[') !== false && strpos($src, ']') !== false) {
$processed_src = do_shortcode($src);
//属性値を更新
return str_replace($src, $processed_src, $matches[0]);
}
//ショートコードが無ければそのまま返す
return $matches[0];
}, $content);
}
add_filter('the_content', 'process_shortcodes_in_script', 99);
拡張: 複数の属性に対応した統合版
より幅広い用途に対応するため、script
のsrc
属性だけでなく、他の属性(href
、onclick
など)でもショートコードを処理できる統合版コードを紹介します:
/* HTML要素の属性内のショートコードを処理する統合関数 */
function process_shortcodes_in_html_attributes($content) {
//高速チェック - ショートコードがなければ処理しない
if (false === strpos($content, '[')) {
return $content;
}
//処理する属性のリスト
$attributes = array('src', 'href', 'onclick', 'data-src');
//各属性に対して処理を行う
foreach ($attributes as $attr) {
//属性を含むタグを検索する正規表現
$pattern = '/(' . $attr . ')=(["\'])([^"\']*?)\2/i';
//コールバック関数で属性値内のショートコードを処理
$content = preg_replace_callback($pattern, function($matches) {
$attr_name = $matches[1]; //属性名
$quote = $matches[2]; //引用符 (' または ")
$attr_value = $matches[3]; //属性値
//ショートコードが含まれる場合のみ処理
if (strpos($attr_value, '[') !== false && strpos($attr_value, ']') !== false) {
$processed_value = do_shortcode($attr_value);
return $attr_name . '=' . $quote . $processed_value . $quote;
}
//ショートコードがなければそのまま返す
return $matches[0];
}, $content);
}
return $content;
}
//フィルターを追加
add_filter('the_content', 'process_shortcodes_in_html_attributes', 99);
$attributes
配列に処理したい属性名を追加するだけで、簡単に対象を拡張できます。例えば、data-*
属性、srcset
、alt
などを追加することも可能です。
使用例
このコードをfunctions.php
に追加後は、固定ページ内で以下のように記述できます:
<link rel="preload" href="[topthemeurl]/js/script.js" as="script">
<script src="[topthemeurl]/js/script.js"></script>
<a href="[topthemeurl]/page.html">リンク</a>
<div data-src="[commonsurl]/images/photo.jpg"></div>
全ての属性でショートコードが正しく展開されます。
レンタルサーバー別の動作状況
サーバー | 方法1 (DOMDocument) | 方法2 (正規表現) | 統合版 |
---|---|---|---|
カラフルボックス | ✅ | ✅ | ✅ |
エックスサーバー | ❌ | ✅ | ✅ |
ヘテムル | ❌ | ✅ | ✅ |
ロリポップ | △ | ✅ | ✅ |
さくらインターネット | △ | ✅ | ✅ |
※ △は設定によって動作が異なる場合があることを示します
まとめ
正規表現を使用した方法2または統合版を使用することで、ほとんどのレンタルサーバーでWordPressの固定ページ内のHTML属性内でショートコードを使用できるようになります。これは特に以下のような場合に便利です:
- テーマのディレクトリパスを動的に管理したい場合
- マルチサイト環境でスクリプトのパスを柔軟に制御したい場合
- 下層に別のWordPressをインストールしている場合のパス管理
- JavaScriptファイルやリソースの参照を一元管理したい場合
安定性を重視する場合は、必ず方法2または統合版を使用することをお勧めします。