1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WordPress:固定ページ内の<script>タグでもショートコードを使えるようにする方法

Last updated at Posted at 2025-02-11

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);

拡張: 複数の属性に対応した統合版

より幅広い用途に対応するため、scriptsrc属性だけでなく、他の属性(hrefonclickなど)でもショートコードを処理できる統合版コードを紹介します:

/* 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-*属性、srcsetaltなどを追加することも可能です。

使用例

このコードを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または統合版を使用することをお勧めします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?