楽天セール開催中!ポイント最大11倍! セール会場へ

WordPress│クラシックエディタで記事の中に他の記事を参照する方法│ショートコードTIPS集

公開済みの記事パーツをスラッグで呼び出すコード例です。

通常の投稿ではなく、カスタム投稿タイプblogpartsの記事パーツを対象にします。

SWELL標準のblog_partsとは別の機能です。

目次

著者

WEB制作をしているデジタルノマド
WordPressのカスタマイズが好きで、色々と自作しています。

WordPressのカスタマイズに困ったらご相談ください!

準備と貼付先

子テーマのfunctions.phpをバックアップし、PHP領域へ追加します。

後述の「本文とテキストフィールドを分けて表示する」のコードには先頭に<?phpがありますが、既存のPHP領域へ追記するときはこの開始タグを重ねず、functionから貼り付けてください。

旧motoki_show_custom_post_type・replace_shortcodeと対応するショートコード登録は外して置き換えます。

以前の記事では同名関数を複数掲載していましたが、複数の例を同時に入れると関数名が重複します。

blogpartsが未登録の場合は、同じfunctions.phpへ次も追加します。

管理画面の「記事パーツ」で本文とスラッグを設定して公開します。公開するパーツには閲覧者へ見せてよい内容だけを保存してください。このコードは会員制のアクセス制御ではなく、投稿タイプのpublicがfalseでも秘密情報の保護を保証しません。

既に登録済みの投稿タイプの設定は変更しません。

ACFを使う場合は記事パーツに適用するフィールドグループを作り、naraをテキスト型、改行を使うosakaをテキストエリア(textarea)型として登録してください。

add_action('init', function () {
    if (!post_type_exists('blogparts')) {
        register_post_type('blogparts', [
            'label' => '記事パーツ', 'public' => false,
            'show_ui' => true, 'show_in_rest' => true,
            'supports' => ['title', 'editor'],
        ]);
    }
});

本文とテキストフィールドを分けて表示する

<?php
function waza_blogpart_post($slug) {
    $slug = sanitize_title($slug);
    if ($slug === '') return null;
    $posts = get_posts(['name'=>$slug, 'post_type'=>'blogparts', 'post_status'=>'publish', 'numberposts'=>1]);
    $post = $posts[0] ?? null;
    return $post && $post->post_type === 'blogparts' && $post->post_status === 'publish' && $post->post_password === '' ? $post : null;
}
function waza_blogpart_content($atts) {
    static $active = [];
    $a = shortcode_atts(['slug'=>''], $atts, 'blogparts');
    $post = waza_blogpart_post($a['slug']);
    if (!$post || isset($active[$post->ID]) || count($active) >= 8) return '';
    $active[$post->ID] = true;
    $previous_post = $GLOBALS['post'] ?? null;
    try {
        // 本文フィルターが投稿情報を変更しても呼出し前の状態へ戻す。
        return apply_filters('the_content', $post->post_content);
    } finally {
        $GLOBALS['post'] = $previous_post;
        if ($previous_post instanceof WP_Post) {
            setup_postdata($previous_post);
        }
        unset($active[$post->ID]);
    }
}
add_shortcode('blogparts', 'waza_blogpart_content');
function waza_blogpart_field($atts) {
    $a = shortcode_atts(['slug'=>'', 'field'=>'', 'find'=>'', 'replace'=>''], $atts, 'blogparts_field');
    if (!function_exists('get_field') || !in_array($a['field'], ['nara', 'osaka'], true)) return '';
    $post = waza_blogpart_post($a['slug']);
    if (!$post) return '';
    $value = get_field($a['field'], $post->ID, false);
    if (!is_scalar($value)) return '';
    $value = (string) $value;
    if ($a['find'] !== '') $value = str_replace($a['find'], $a['replace'], $value);
    return nl2br(esc_html($value));
}
add_shortcode('blogparts_field', 'waza_blogpart_field');

本文を表示する

[blogparts slug="test"]

testは公開済みblogparts記事のスラッグへ置き換えます。

パスワード付き・下書き・存在しない記事は表示しません。

同じパーツへの循環参照は停止し、最大8階層までとしています。

埋め込み先のグローバル記事は入れ替えないため、動的な処理が参照先の記事IDを必要とする場合は明示的にIDを渡す設計が必要です。

ACFのテキストを表示・置換する

[blogparts_field slug="test" field="nara"]
[blogparts_field slug="test" field="osaka" find="醤油ラーメン" replace="塩ラーメン"]

fieldはコード内で許可したnara・osakaだけを読みます。

実際に公開してよいテキストフィールド名へ変更してください。

ACFが無効なら空文字です。

文字列の置換はHTMLへ変換する前に行い、値をエスケープして表示します。ACFのget_field()の第3引数をfalseにして未整形値を取得し、文字として表示するためにesc_html()を通しています。

配列や繰り返しフィールド、HTMLをそのまま出す用途には対応していません。

旧例の本文HTML全体に対するstr_replaceや、未エスケープのACF値の連結は撤去しました。

ACF繰り返しとプレースホルダー埋め込みの旧コードは、そのまま混在させず別途データ構造を定義して実装する必要があります。

記事パーツの編集保存から表示まで確認する

ACF 6.8.10の編集画面で、naraをテキスト型、osakaをtextarea型として登録した公開blogpartsを更新しました。

再表示でnaraの文字列0とosakaの改行を保持し、参照ページにパーツ本文と両フィールドが表示されることを確認しました。

osakaに「醤油ラーメン」とHTMLタグを含む文字列を保存したところ、呼び出し側の指定で「塩ラーメン」へ置換され、HTMLタグは文字として表示されました。

改行は残り、script要素は生成されませんでした。

スマホ幅385pxでも0・置換後の文字列・二行目を表示し、横にはみ出しませんでした。

確認するときは、パーツの本文を呼ぶblogpartsと、ACF値を読むblogparts_fieldを分けて試してください。

本文が表示されてもフィールド欄が空なら、フィールドグループの適用先、許可名、保存した型を確認します。

配列を返す型はこのコードの対象外です。

保存した記事パーツとACF値を表示するスマホ幅の画面
保存したパーツ本文とACFの0・置換後の文字列を表示した画面。2026年10月3日、隔離したWordPress 7.1.2 / SWELL 2.19.0で撮影。

複数パーツを呼ぶ場合は公開状態も個別に確認する

参照したパーツ本文の出力
別スラッグの公開パーツA・B両方の本文を表示
非公開のパーツ本文を表示しない
公開状態でもパスワード付き本文を表示しない

異なるスラッグの公開パーツを同じ投稿から呼び出し、両方が表示されることを確認しました。

同じ投稿から非公開・パスワード付きのパーツも参照しましたが、これらの本文は出力されませんでした。

スラッグが実在するかだけでなく、参照先の投稿タイプ、公開状態、パスワードの有無を照合します。

既存のパーツを更新するときはA・Bの本文が混ざらないことを確認し、呼び出し元の投稿IDに依存する処理は別に確認してください。

パーツ本文の処理後に投稿と著者情報を戻す

パーツ本文にはthe_contentのフィルターが適用されます。

パーツの中にSWELLのブログパーツや投稿リストを含めると、その内部処理が投稿情報を変更する場合があります。

掲載コードでは、呼出し直前のグローバル投稿を保存し、finallyで戻します。元の投稿がWP_Postの場合だけ、setup_postdata()で著者などの投稿データを再設定します。元の投稿がない場合や、フィルターが変更する任意のグローバル変数まで完全に復元する設計ではありません。

循環参照を防ぐ処理も維持します。

過去の隔離したWordPress 7.1.2とSWELL 2.19.0では、別著者の投稿ループ、投稿が設定されていない呼出し、描画中の例外を確認した記録があります。2026年10月21日の本文見直しでは、その動作試験を再実行していません。

公開中の利用先でのキャッシュ、PC・スマホ表示と操作は別に確認します。

確認と戻し方

存在するスラッグ・存在しないスラッグ・自己参照・非公開・ACF未有効・文字列0で確認します。

パーツ内のリンクや画像はPC・スマホ幅とキーボードでも確認してください。

解除時は本文から呼び出しを外し、追加した関数と登録をまとめて戻します。

パーツ本体やフィールド値は削除しません。

関連:SCFの値を記事IDを指定して表示する方法。

旧GitHub例は今回の修正と同期していません。

よくある質問:クラシックエディタで記事の中に他の記事(記事パーツ)を参照するとき

この方法では、何を呼び出せますか?

記事では、公開済みの記事パーツをスラッグで呼び出すコード例です。通常の投稿ではなく、カスタム投稿タイプblogpartsの記事パーツが対象で、SWELL標準のブログパーツとは別の機能です。

コードは、どこに追加しますか?

記事では、子テーマのfunctions.phpをバックアップし、PHP領域へ追加します。既存のPHP領域へ追記するときは、先頭のPHP開始タグを重ねません。旧版の関数と対応するショートコード登録は外して置き換えます。複数の例を同時に入れると関数名が重複します。

blogpartsが未登録のときは、どうしますか?

記事では、同じfunctions.phpへ登録用のコードも追加します。管理画面の「記事パーツ」で本文とスラッグを設定して公開します。既に登録済みの投稿タイプの設定は変更しません。

どんな記事パーツが表示されますか?

記事では、パスワード付き・下書き・存在しない記事は表示しません。同じパーツへの循環参照は停止し、最大8階層までとしています。異なるスラッグの公開パーツを同じ投稿から呼び出すと両方が表示され、非公開・パスワード付きのパーツ本文は出力されませんでした。

ACFのテキストも、表示できますか?

できます。記事では、ACFを使う場合は記事パーツに適用するフィールドグループを作り、テキスト型と、改行を使うテキストエリア型のフィールドを登録します。パーツの本文を呼ぶものと、ACF値を読むものを分けて試します。配列を返す型はこのコードの対象外です。

本文は表示されるのに、フィールド欄が空のときは?

記事では、フィールドグループの適用先、許可名、保存した型を確認します。

HTMLタグを含む文字列は、どう表示されますか?

記事では、HTMLタグを含む文字列を保存したところ、HTMLタグは文字として表示され、改行は残り、script要素は生成されませんでした。呼び出し側の指定で文字列の置換もできます。

公開前に、何を確認しますか?

記事では、存在するスラッグ・存在しないスラッグ・自己参照・非公開・ACF未有効・文字列0で確認します。パーツ内のリンクや画像は、PC・スマホ幅とキーボードでも確認します。解除時は、本文から呼び出しを外し、追加した関数と登録をまとめて戻します。パーツ本体やフィールド値は削除しません。

  • URLをコピーしました!

実装を任せたい方へ

WordPressのカスタマイズ代行

ブロックの追加、テーマの改修、管理画面の調整など、記事で紹介している内容の実装を承ります。1時間 ¥8,000〜(税込)。

WAZAの有料記事のサブスクリプションも開始しました。

サービス

Service

WordPressサイトのカスタマイズのサービスに関心がありましたら、ぜひ詳細をご覧ください。

目次