2026年9月24日

2026年9月24日

WordPressのテーマテンプレートエラーを解決する方法

はじめに

WordPressでカスタム投稿タイプの単一記事ページにsingle-{post_type}.phpを作成したのに読み込まれない・固定ページに特定のテンプレートを割り当てたはずなのに反映されない・get_template_part()で読み込もうとしたファイルが見つからない・子テーマに追加したテンプレートファイルが親テーマのものに上書きされてしまうといった問題は、WordPressのテンプレート階層と読み込みルールを理解することで解決できます。

症状・原因

  • テンプレートファイルの命名規則が間違っており、WordPressのテンプレート階層に一致していない
  • 子テーマと親テーマの両方に同名テンプレートがあり、期待と逆の優先順位で読み込まれている
  • get_template_part()のスラッグ・名前引数のパスが正しくなく、ファイルが見つからない
  • ページテンプレートのPHPファイルヘッダーコメントのTemplate Name:が記述されていない

解決手順

ステップ1:テンプレート読み込みをデバッグする

# 現在使用しているテンプレートを確認
wp eval "
add_filter('template_include', function(\$template) {
    error_log('Template: ' . \$template);
    return \$template;
});
"

# テンプレート階層を確認(WP_DEBUG 時)
wp eval "
add_filter('template_include', function(\$template) {
    echo basename(\$template);
    return \$template;
}, 999);
"

# テンプレートの探索順を確認
wp eval "
// 例:カスタム投稿タイプ 'product' の単一記事
\$templates = [
    'single-product-{slug}.php',
    'single-product.php',
    'single.php',
    'singular.php',
    'index.php',
];
foreach (\$templates as \$tpl) {
    \$path = locate_template(\$tpl);
    echo \$tpl . ': ' . (\$path ? '✓ ' . \$path : '× なし') . PHP_EOL;
}
"

# 固定ページのテンプレートを確認
wp eval "
\$page_id = 5;
echo get_page_template_slug(\$page_id) ?: 'デフォルトテンプレート';
"

ステップ2:テンプレート階層を正しく理解する

WordPressのテンプレート階層(優先度順)

■ 単一投稿 (single post):
  single-{post_type}-{slug}.php
  single-{post_type}.php
  single.php → singular.php → index.php

■ 固定ページ (page):
  {custom-template}.php  ← ページ属性で指定
  page-{slug}.php
  page-{id}.php
  page.php → singular.php → index.php

■ カスタム投稿タイプアーカイブ:
  archive-{post_type}.php
  archive.php → index.php

■ カテゴリーアーカイブ:
  category-{slug}.php
  category-{id}.php
  category.php → archive.php → index.php

■ 検索結果: search.php → index.php
■ 404: 404.php → index.php
■ フロントページ: front-page.php → home.php → index.php
// ✅ テンプレートフィルターで動的にテンプレートを変更
add_filter('single_template', function(string $template): string {
    if (get_post_type() === 'product') {
        $custom = get_stylesheet_directory() . '/templates/single-product.php';
        if (file_exists($custom)) {
            return $custom;
        }
    }
    return $template;
});

// ✅ ページテンプレートをプラグインから登録する
add_filter('theme_page_templates', function(array $templates): array {
    $templates['templates/my-landing-page.php'] = 'ランディングページ';
    return $templates;
});

// ✅ template_include でリクエストに応じてテンプレートを完全に差し替え
add_filter('template_include', function(string $template): string {
    // 特定のクエリ変数に応じてテンプレートを変更
    if (get_query_var('my_custom_page') === 'dashboard') {
        $custom = get_stylesheet_directory() . '/templates/dashboard.php';
        if (file_exists($custom)) {
            return $custom;
        }
    }
    return $template;
});

ステップ3:get_template_partを正しく使う

// ✅ get_template_part の正しい使い方
// ファイル: {theme}/template-parts/content/post.php

// WP 5.5 以降の書き方($args で変数を渡せる)
get_template_part('template-parts/content', 'post', [
    'post_id'     => get_the_ID(),
    'show_excerpt' => true,
    'image_size'   => 'medium',
]);

// テンプレートパーツファイル内での引数の受け取り方:
// template-parts/content/post.php:
$args        = wp_parse_args($args, [
    'post_id'     => 0,
    'show_excerpt' => false,
    'image_size'   => 'thumbnail',
]);
$post_id      = absint($args['post_id']);
$show_excerpt = (bool) $args['show_excerpt'];

// ✅ locate_template でファイルの存在を確認してから読み込む
$template = locate_template([
    'template-parts/card-' . get_post_type() . '.php',
    'template-parts/card.php',
]);
if ($template) {
    load_template($template, false, ['post_id' => get_the_ID()]);
}

// ✅ プラグインからテンプレートを提供する(テーマで上書き可能)
function my_plugin_get_template(string $template_name, array $args = []): void {
    // 1. 子テーマで上書き可能
    $theme_file = locate_template('my-plugin/' . $template_name);
    if ($theme_file) {
        load_template($theme_file, false, $args);
        return;
    }

    // 2. プラグインのデフォルトテンプレート
    $plugin_file = MY_PLUGIN_DIR . 'templates/' . $template_name;
    if (file_exists($plugin_file)) {
        load_template($plugin_file, false, $args);
    }
}

ステップ4:ページテンプレートを正しく作成する

<?php
/**
 * Template Name: ランディングページ
 * Template Post Type: page, post
 *
 * ↑ このコメントが必須。Template Name が表示名になる
 */

// ✅ 直接アクセスを禁止
if (!defined('ABSPATH')) {
    exit;
}

get_header();
?>

<main id="main" class="site-main lp-main">
    <?php while (have_posts()) : the_post(); ?>
        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <div class="entry-content">
                <?php the_content(); ?>
            </div>
        </article>
    <?php endwhile; ?>
</main>

<?php
// ✅ フッターは必ず get_footer() で(wp_footer() が実行される)
get_footer();

ステップ5:テンプレートのデバッグと最適化

// ✅ 現在のテンプレートファイルを管理バーに表示
add_action('wp_before_admin_bar_render', function(): void {
    if (!current_user_can('manage_options') || !is_admin_bar_showing()) {
        return;
    }

    global $wp_admin_bar, $template;
    $wp_admin_bar->add_node([
        'id'    => 'current-template',
        'title' => '📄 ' . basename($template ?? ''),
        'href'  => false,
    ]);
});

// ✅ template_redirect でリダイレクト
add_action('template_redirect', function(): void {
    // 非公開投稿へのアクセスをリダイレクト
    if (is_singular() && !current_user_can('read_post', get_the_ID())) {
        wp_redirect(home_url('/'));
        exit;
    }

    // カスタムクエリ変数によるページ切り替え
    if (get_query_var('my_page') === 'thankyou') {
        include get_stylesheet_directory() . '/templates/thankyou.php';
        exit;
    }
});

// ✅ テンプレートのコンテキストを確認するデバッグ関数
function my_debug_template_context(): void {
    if (!current_user_can('manage_options')) {
        return;
    }
    $context = [
        'is_front_page' => is_front_page(),
        'is_home'       => is_home(),
        'is_singular'   => is_singular(),
        'is_archive'    => is_archive(),
        'post_type'     => get_post_type(),
        'queried_object'=> get_class(get_queried_object()),
    ];
    echo '<!-- Template context: ' . wp_json_encode($context) . ' -->';
}

注意事項

  • ページテンプレートとして使うPHPファイルには必ずファイル先頭に/ Template Name: テンプレート名 /コメントを記述してください。このコメントがないとWordPressはそのファイルをページテンプレートとして認識せず、管理画面の「テンプレート」ドロップダウンに表示されません
  • get_template_part()はWP 5.5以降で第3引数($args)を使えますが、それ以前のバージョンとの互換性が必要な場合はset_query_var()とget_query_var()でデータを渡してください

まとめ

WordPressのテーマテンプレートエラーの解決は①template_includeフィルターで現在のテンプレートをログ・locate_template()で探索確認、②テンプレート階層の優先順位を理解(single-{type}-{slug}.php → single-{type}.php → single.php)・single_templateフィルターでプログラムから変更、③get_template_part(slug, name, $args)で変数を渡す・locate_template()+load_template()で条件付き読み込み・プラグインテンプレートはテーマで上書き可能に設計、④ページテンプレートはTemplate Name: 名前コメントが必須・template_post_typeで対応投稿タイプを制限、⑤管理バーにテンプレート名を表示・template_redirectでリダイレクトや差し替えの手順で解決します。

お気軽にご相談ください

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