【WordPress】トップページにカスタム投稿タイプを表示する方法|esc_html・dynamic_sidebar・do_shortcode

WordPressのカスタム投稿タイプを活用すると、ウェブサイトの柔軟性を大幅に向上させることができます。この記事では、カスタム投稿タイプの投稿をトップページに表示する3つの方法を、見落としがちな実装漏れも含めて解説します。

この記事でわかること

  • カスタムループWP_Query)で直接表示する方法
  • ウィジェットで管理画面から追加できるようにする方法
  • ショートコードで手軽に呼び出す方法
スポンサーリンク

カスタムループを使う

WP_Query を使って、カスタム投稿タイプの投稿を取得して表示します。

functions.phpにカスタムループを追加する

functions.php:カスタム投稿タイプを取得する関数
function custom_post_type_loop() {
    $args = array(
        'post_type'      => 'your_custom_post_type', // カスタム投稿タイプのスラッグ
        'posts_per_page' => 5,      // 表示する投稿数
        'orderby'        => 'date', // 日付順で並べ替え
        'order'          => 'DESC', // 降順で表示(新しい投稿が先)
    );

    $query = new WP_Query( $args );

    if ( $query->have_posts() ) {
        echo '<ul>';
        while ( $query->have_posts() ) {
            $query->the_post();
            echo '<li><a href="' . esc_url( get_permalink() ) . '">'
                . esc_html( get_the_title() ) . '</a></li>';
        }
        echo '</ul>';
    }

    wp_reset_postdata();
}

トップページテンプレートに表示する

トップページ(front-page.php)の任意の場所に、作成した関数を呼び出すコードを挿入します。

front-page.php:カスタムループを呼び出す
<div class="custom-post-type-section">
    <h2>カスタム投稿タイプのタイトル</h2>
    <?php custom_post_type_loop(); ?>
</div>

ウィジェットを使う

カスタムウィジェットを作成し、管理画面からトップページに配置できるようにする方法です。

functions.phpでウィジェットエリアを登録する

functions.php:ウィジェットエリアの登録
function custom_post_type_widget_init() {
    register_sidebar( array(
        'name'          => 'カスタム投稿タイプウィジェットエリア',
        'id'            => 'custom_post_type_widget_area',
        'before_widget' => '<div class="widget">',
        'after_widget'  => '</div>',
        'before_title'  => '<h2 class="widget-title">',
        'after_title'   => '</h2>',
    ) );
}
add_action( 'widgets_init', 'custom_post_type_widget_init' );

front-page.phpでウィジェットエリアを表示する

register_sidebar() はウィジェットエリアを登録するだけで、画面に表示するには別途 dynamic_sidebar() をテンプレートファイルに書く必要があります。

front-page.php:ウィジェットエリアを描画する
if ( is_active_sidebar( 'custom_post_type_widget_area' ) ) {
    dynamic_sidebar( 'custom_post_type_widget_area' );
}
登録しただけでは何も表示されない
register_sidebar() でウィジェットエリアを登録し、管理画面からウィジェットを追加しても、テンプレート側で dynamic_sidebar() を呼び出していなければトップページには何も表示されません。「登録」と「表示」は別のステップであることを忘れないでください。

カスタムウィジェットを作成する

カスタム投稿タイプの投稿一覧を表示するウィジェットを作成し、上記のウィジェットエリアに追加できるようにします。

functions.php:カスタム投稿タイプ用ウィジェット
class Custom_Post_Type_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'custom_post_type_widget',
            'カスタム投稿タイプウィジェット',
            array( 'description' => 'カスタム投稿タイプの投稿を表示します。' )
        );
    }

    public function widget( $args, $instance ) {
        $title = apply_filters( 'widget_title', $instance['title'] );

        echo $args['before_widget'];
        if ( ! empty( $title ) ) {
            echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
        }

        $query_args = array(
            'post_type'      => 'your_custom_post_type',
            'posts_per_page' => 5,
            'orderby'        => 'date',
            'order'          => 'DESC',
        );

        $query = new WP_Query( $query_args );

        if ( $query->have_posts() ) {
            echo '<ul>';
            while ( $query->have_posts() ) {
                $query->the_post();
                echo '<li><a href="' . esc_url( get_permalink() ) . '">'
                    . esc_html( get_the_title() ) . '</a></li>';
            }
            echo '</ul>';
        }

        wp_reset_postdata();

        echo $args['after_widget'];
    }

    public function form( $instance ) {
        $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
        ?>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">タイトル:</label>
            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
                name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
                type="text" value="<?php echo esc_attr( $title ); ?>">
        </p>
        <?php
    }

    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) )
            ? sanitize_text_field( $new_instance['title'] ) : '';

        return $instance;
    }
}

function register_custom_post_type_widget() {
    register_widget( 'Custom_Post_Type_Widget' );
}
add_action( 'widgets_init', 'register_custom_post_type_widget' );

ウィジェットエリアにウィジェットを追加する

WordPress管理画面の「外観」>「ウィジェット」から、「カスタム投稿タイプウィジェットエリア」に作成したウィジェットを追加します。

ショートコードを使う

ショートコードを使えば、固定ページや投稿の本文から手軽にカスタム投稿タイプの一覧を呼び出せます。

functions.phpでショートコードを定義する

functions.php:ショートコードの定義
function custom_post_type_shortcode( $atts ) {
    $atts = shortcode_atts( array(
        'post_type'      => 'your_custom_post_type',
        'posts_per_page' => 5,
        'orderby'        => 'date',
        'order'          => 'DESC',
    ), $atts, 'custom_post_type' );

    $args = array(
        'post_type'      => $atts['post_type'],
        'posts_per_page' => intval( $atts['posts_per_page'] ),
        'orderby'        => $atts['orderby'],
        'order'          => $atts['order'],
    );

    $query = new WP_Query( $args );

    ob_start();
    if ( $query->have_posts() ) {
        echo '<ul>';
        while ( $query->have_posts() ) {
            $query->the_post();
            echo '<li><a href="' . esc_url( get_permalink() ) . '">'
                . esc_html( get_the_title() ) . '</a></li>';
        }
        echo '</ul>';
    }

    wp_reset_postdata();

    return ob_get_clean();
}
add_shortcode( 'custom_post_type', 'custom_post_type_shortcode' );

固定ページ・投稿の本文でショートコードを使う

固定ページや投稿の編集画面の本文に、そのまま書くだけで動作します。

固定ページ・投稿の本文に貼り付け
[custom_post_type]

引数を指定してカスタマイズすることも可能です。

引数を指定する場合
[custom_post_type post_type="your_custom_post_type" posts_per_page="5"]
PHPテンプレートファイル内では do_shortcode() が必要
ショートコードは、投稿・固定ページの本文が the_content フィルターを通る際に展開される仕組みです。front-page.php のようなPHPテンプレートファイルの中に [custom_post_type] という文字列をそのまま書いても実行されません。テンプレートファイルの中で使いたい場合は、do_shortcode() で囲んでください。
front-page.php:テンプレート内でショートコードを使う場合
<?php echo do_shortcode( '[custom_post_type]' ); ?>

関連するカスタム投稿タイプの実装

よくある質問(FAQ)

Qフロントページにカスタム投稿タイプの記事を表示するWP_Queryの書き方は?
Anew WP_Query(array('post_type' => 'custom_type', 'posts_per_page' => 5))でクエリを組みます。フロントページのテンプレート(front-page.phpなど)内で独立したループとして実装します。
Qpre_get_postsフックでメインループにカスタム投稿タイプを含める方法は?
Aadd_action('pre_get_posts', function($q){ if($q->is_home() && $q->is_main_query()){ $q->set('post_type', array('post', 'custom_type')); } }); をfunctions.phpに追加します。
Qカスタム投稿タイプをトップページに表示する際のパフォーマンス対策は?
Aposts_per_pageを適切に制限し、不要なフィールドを取得しないようfields='ids'を使う、またはTransients APIでキャッシュすることで負荷を軽減できます。

まとめ

  • カスタムループWP_Queryで直接表示。柔軟性が高い
  • ウィジェットregister_sidebar()dynamic_sidebar()の両方が必要(登録だけでは表示されない)
  • ショートコード:本文ならそのまま、テンプレート内ならdo_shortcode()が必要
  • 共通:出力は必ずesc_url()/esc_html()でエスケープする

サイトの構成やカスタマイズの自由度に応じて、最適な方法を選んでください。