2026年5月20日

2026年5月20日

WordPressの投稿ページテンプレートを作成する方法

はじめに

WordPressの投稿詳細ページは single.php テンプレートで制御します。カスタム投稿タイプには single-{post_type}.php を使い、関連記事・著者情報・前後ナビゲーションを追加することでユーザー体験が向上します。

症状・原因

  • 投稿詳細ページのデザインを変更したい
  • カスタム投稿タイプごとに異なるレイアウトを使いたい
  • 投稿詳細に関連記事を表示したい
  • 著者プロフィールボックスを追加したい

解決手順

ステップ1:テンプレート階層を理解する

投稿詳細のテンプレート階層(優先度高い順):

通常の投稿(post):
  single-post-{slug}.php → single-post.php → single.php → singular.php → index.php

カスタム投稿タイプ(news):
  single-news-{slug}.php → single-news.php → single.php → singular.php → index.php

固定ページ:
  {page-template}.php → page-{slug}.php → page-{id}.php → page.php → singular.php

ステップ2:single.phpの基本構造を作成する

<?php
// wp-content/themes/my-child-theme/single.php
get_header();
?>
<main class="single-post">
    <?php while (have_posts()): the_post(); ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <header class="entry-header">
                <?php the_title('<h1 class="entry-title">', '</h1>'); ?>
                <div class="entry-meta">
                    <time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date(); ?></time>
                    <?php the_category(', '); ?>
                    <?php the_tags('<span class="tags">', ', ', '</span>'); ?>
                </div>
                <?php if (has_post_thumbnail()): ?>
                    <div class="featured-image">
                        <?php the_post_thumbnail('large'); ?>
                    </div>
                <?php endif; ?>
            </header>

            <div class="entry-content">
                <?php the_content(); ?>
                <?php wp_link_pages(); ?>
            </div>

            <footer class="entry-footer">
                <?php // 著者情報ボックス ?>
                <?php get_template_part('template-parts/author-bio'); ?>

                <?php // 前後の記事ナビゲーション ?>
                <?php the_post_navigation([
                    'prev_text' => '← %title',
                    'next_text' => '%title →',
                ]); ?>
            </footer>
        </article>

        <?php // 関連記事 ?>
        <?php get_template_part('template-parts/related-posts'); ?>

        <?php // コメント ?>
        <?php if (comments_open() || get_comments_number()): ?>
            <?php comments_template(); ?>
        <?php endif; ?>

    <?php endwhile; ?>
</main>
<?php get_sidebar(); get_footer(); ?>

ステップ3:関連記事を表示する

// template-parts/related-posts.php を作成
<?php
$categories  = get_the_category();
if (empty($categories)) return;

$category_ids = wp_list_pluck($categories, 'term_id');

$related = new WP_Query([
    'category__in'   => $category_ids,
    'post__not_in'   => [get_the_ID()],
    'posts_per_page' => 4,
    'orderby'        => 'rand',
]);

if (!$related->have_posts()) return;
?>
<section class="related-posts">
    <h2>関連記事</h2>
    <div class="related-posts-grid">
        <?php while ($related->have_posts()): $related->the_post(); ?>
            <article class="related-post-card">
                <a href="<?php the_permalink(); ?>">
                    <?php if (has_post_thumbnail()): ?>
                        <?php the_post_thumbnail('thumbnail'); ?>
                    <?php endif; ?>
                    <h3><?php the_title(); ?></h3>
                </a>
            </article>
        <?php endwhile; wp_reset_postdata(); ?>
    </div>
</section>

ステップ4:著者情報ボックスを追加する

// template-parts/author-bio.php を作成
<?php
$author_id = get_the_author_meta('ID');
$bio       = get_the_author_meta('description');
if (empty($bio)) return;
?>
<div class="author-bio">
    <div class="author-avatar">
        <?php echo get_avatar($author_id, 80); ?>
    </div>
    <div class="author-info">
        <h3 class="author-name"><?php the_author(); ?></h3>
        <p class="author-description"><?php echo esc_html($bio); ?></p>
        <a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>">
            この著者の記事一覧
        </a>
    </div>
</div>

ステップ5:カスタム投稿タイプ専用テンプレートを作る

# single-news.php を作成(newsカスタム投稿タイプ専用)
cp wp-content/themes/my-child-theme/single.php \
   wp-content/themes/my-child-theme/single-news.php

# テンプレートが認識されているか確認
wp eval "
\$post = get_post(get_option('page_on_front'));
echo locate_template('single-news.php') . PHP_EOL;
"

# 現在の投稿タイプ一覧
wp post-type list --format=table

ステップ6:構造化データ(JSON-LD)を追加する

// functions.php — 記事にJSON-LD構造化データを追加
add_action('wp_head', function(): void {
    if (!is_single()) return;

    $schema = [
        '@context'      => 'https://schema.org',
        '@type'         => 'Article',
        'headline'      => get_the_title(),
        'datePublished' => get_the_date('c'),
        'dateModified'  => get_the_modified_date('c'),
        'author'        => [
            '@type' => 'Person',
            'name'  => get_the_author(),
        ],
        'image'         => get_the_post_thumbnail_url(null, 'large') ?: '',
    ];

    echo '<script type="application/ld+json">'
        . wp_json_encode($schema, JSON_UNESCAPED_UNICODE)
        . '</script>' . PHP_EOL;
});

注意事項

  • WP_Query で関連記事を取得した後は wp_reset_postdata() を必ず呼び出してください
  • single-{post_type}.php を作成することで投稿タイプごとに完全に異なるレイアウトが実現できます
  • the_post_navigation() は前後の投稿へのナビゲーションを表示します。同じカテゴリー内に絞る場合は in_same_term オプションを使います

まとめ

投稿詳細ページは single.phpsingle-{post_type}.php のテンプレートで構築します。template-parts/ にパーツ化した関連記事・著者情報を追加し、the_post_navigation() で前後ナビゲーションを実装しましょう。

お気軽にご相談ください

お見積りへ お問い合わせへ