要点
- the_field()は基本的にショートコードを実行しません(WYSIWYG は除く)。
- もっとも安全で壊れにくい方法は get_field()→do_shortcode()の手動ラップ。
- 規模が大きいなら ACFの acf/format_valueフィルタで型や名前ごとに自動化。
- セキュリティと可読性のため、許可リスト/権限チェックを入れておくのが実務的。
1) まずは前提:どのフィールドが“そのままでは”動くのか?
- WYSIWYG(エディタ):the_content相当の処理が入るため、ショートコードは実行される。
- テキスト/テキストエリア/数値 など:実行されない(ただの文字列として出力)。
つまり、WYSIWYG 以外のフィールドでショートコードを使いたいときに以下の方法を使います。
2) 手早く確実:get_field() を do_shortcode() で包む
テンプレート側のピンポイント対応。副作用が少なく、まずはこれでOK。
<?php
// テンプレート例
$value = get_field('my_text_field'); // the_field()は即出力なので使わない
if (!empty($value)) {
    echo do_shortcode($value);
}ポイント
- the_field()は即出力&加工できないので- get_field()を使う。
- 何でもかんでも do_shortcode()するのは危険。この方法は適用箇所を限定できるのが強み。
3) 規模が大きいなら:acf/format_value で自動化
3-1. フィールド名を指定して実行(局所適用)
<?php
// functions.php
add_filter('acf/format_value/name=my_text_field', function ($value) {
    if (is_string($value) && $value !== '') {
        $value = do_shortcode($value);
    }
    return $value;
}, 10, 1);3-2. 型(テキストエリア等)を一括で実行(広域適用)
<?php
// 例:textarea型の値に限ってショートコードを展開
add_filter('acf/format_value/type=textarea', function ($value) {
    if (is_string($value) && $value !== '') {
        // 段落ズレ対策でunautop→do_shortcodeの順にかけることもある
        $value = shortcode_unautop($value);
        $value = do_shortcode($value);
    }
    return $value;
}, 10, 1);運用Tips
- 一括適用は便利な反面、想定外の場所でもショートコードが動く可能性。
- まずは フィールド名限定で導入 → 影響範囲を確認 → 必要なら型単位に拡張、が安全。
4) セキュリティと運用のベストプラクティス
4-1. 許可するショートコードをホワイトリスト化
<?php
// 許可リスト
function my_allowed_shortcodes(): array {
    return ['gallery', 'contact-form-7', 'my_shortcode'];
}
// 許可されたものだけを展開する実行関数
function my_safe_do_shortcode(string $text): string {
    // 文中から[xxx]を抽出して検査する簡易例
    preg_match_all('/\[([a-zA-Z0-9_-]+)/', $text, $m);
    $tags = array_unique($m[1] ?? []);
    $allowed = my_allowed_shortcodes();
    foreach ($tags as $tag) {
        if (!in_array($tag, $allowed, true)) {
            // 許可外ショートコードは文字列のまま残す(あるいは除去)
            // ここでは除去例:
            $text = preg_replace('/\[' . preg_quote($tag, '/') . '[^\]]*\](?:.*?\[\/' . preg_quote($tag, '/') . '\])?/s', '', $text);
        }
    }
    return do_shortcode($text);
}上の関数に置き換えるだけで、予期しないショートコードの実行を防止できます。
4-2. 投稿権限で挙動を変える(一般ユーザーが編集するサイト向け)
<?php
add_filter('acf/format_value/name=my_text_field', function ($value) {
    if (!is_string($value) || $value === '') return $value;
    // 管理者のみフル許可、それ以外はホワイトリスト実行
    if (current_user_can('manage_options')) {
        return do_shortcode($value);
    }
    return my_safe_do_shortcode($value);
}, 10, 1);4-3. XSS対策(任意のHTML混入が懸念される場合)
<?php
add_filter('acf/format_value/name=my_text_field', function ($value) {
    if (!is_string($value) || $value === '') return $value;
    $value = my_safe_do_shortcode($value);
    // 許可HTMLだけを通す(必要に応じて $allowed_html を拡張)
    $allowed_html = wp_kses_allowed_html('post');
    return wp_kses($value, $allowed_html);
}, 10, 1);5) よくあるハマりどころと対処
- 改行や段落が崩れる
- shortcode_unautop()を- do_shortcode()の前に。
- ACF 側の「自動整形(改行→)」設定や、WYSIWYG のツールバー/整形オプションを見直す。
- 入れ子ショートコードが動かない
- 実装順序(shortcode_unautop→do_shortcode)と、目的のショートコードが適切にadd_shortcode()済みか確認。
- パフォーマンス懸念
- ショートコードの中で重いクエリを回していると遅くなる。
- 可能なら wp_cache_*で結果キャッシュ、WP_Query は最小化。
- WYSIWYGで二重整形
- WYSIWYG は元から整形が入るため、追加で wpautop()をかけない。必要なら ACF の設定側で自動整形をOFF。
6) 動作確認のための最小ショートコード例
<?php
// functions.php
add_shortcode('hello_box', function ($atts, $content = '') {
    $atts = shortcode_atts(['title' => 'Hello'], $atts, 'hello_box');
    // ここでHTMLを返す(必要ならwp_ksesで絞る)
    $title = esc_html($atts['title']);
    $content = wpautop(do_shortcode($content)); // ネスト対応
    return "<div class=\"hello-box\"><h3>{$title}</h3>{$content}</div>";
});ACFのテキストエリアに以下を保存して、上記のいずれかの方法で展開してください。
[hello_box title="ようこそ"]ここに本文や[gallery]など[/hello_box]7) 導入パターン別のおすすめ
- 小規模/箇所限定:テンプレートで get_field()→do_shortcode()
- 中〜大規模/同型多数:acf/format_value/name=...でフィールド名をホワイトリスト運用
- サイト全体で積極運用:型単位(type=textareaなど)+my_safe_do_shortcodeで安全網を張る
まとめ
- WYSIWYG以外のACFフィールドでショートコードを動かすには、
- 手動ラップ(局所)か、2) acf/format_value(自動化)を使う。
- 運用では 許可リスト・権限・XSS対策 をセットで。
- 改行・段落崩れは shortcode_unautop()の併用と整形設定の見直しで解消。

 
  
  
  
  

コメント