WordPressオリジナルテーマ開発②|投稿一覧・固定ページの作り方とfunctions.phpの基本


はじめに

前回の記事ではHTMLサイトをWordPressオリジナルテーマに変換する第一歩として、テーマフォルダの構成・style.css へのテーマ情報の記載・get_template_directory_uri() を使ったパスの書き換え・header.phpfooter.php への分割まで解説しました。今回はWordPressの投稿一覧ページ・固定ページのテンプレートファイルの作り方と、functions.php を使ってテーマをさらに使いやすくする方法をお届けします。


1. WordPressのテンプレート階層を理解する

1.1 テンプレート階層とは

WordPressはURLにアクセスがあったとき「どのテンプレートファイルを使って表示するか」を一定のルールで自動的に判断します。この仕組みをテンプレート階層と呼びます。

表示するページ使われるテンプレートファイル(優先順)
トップページ(ブログ)front-page.phphome.phpindex.php
投稿一覧home.phpindex.php
個別投稿single.phpsingular.phpindex.php
固定ページpage.phpsingular.phpindex.php
カテゴリーアーカイブcategory-{slug}.phpcategory.phparchive.phpindex.php
検索結果search.phpindex.php
404ページ404.phpindex.php

💡 どのファイルも存在しない場合は index.php が使われます: これが前回の作業で index.php だけあればとりあえず動いた理由です。ページの種類が増えてきたら専用のテンプレートファイルを追加していきます。


2. 投稿一覧ページを作る(home.php)

2.1 home.phpを新規作成する

ブログの投稿一覧を表示するテンプレートとして home.php を作成します。

<?php get_header(); ?>

<main class="site-main">
    <div class="container">

        <h1 class="page-title">ブログ</h1>

        <?php if ( have_posts() ) : ?>

            <div class="posts-grid">

                <?php while ( have_posts() ) : the_post(); ?>

                    <article class="post-card" id="post-<?php the_ID(); ?>">

                        <?php if ( has_post_thumbnail() ) : ?>
                            <a href="<?php the_permalink(); ?>" class="post-card__thumb">
                                <?php the_post_thumbnail( 'medium' ); ?>
                            </a>
                        <?php endif; ?>

                        <div class="post-card__body">

                            <div class="post-card__meta">
                                <time datetime="<?php echo get_the_date( 'Y-m-d' ); ?>">
                                    <?php echo get_the_date(); ?>
                                </time>
                                <span class="post-card__cat">
                                    <?php the_category( '・' ); ?>
                                </span>
                            </div>

                            <h2 class="post-card__title">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </h2>

                            <p class="post-card__excerpt">
                                <?php the_excerpt(); ?>
                            </p>

                            <a href="<?php the_permalink(); ?>" class="post-card__more">
                                続きを読む
                            </a>

                        </div>

                    </article>

                <?php endwhile; ?>

            </div>

            <!-- ページネーション -->
            <div class="pagination">
                <?php the_posts_pagination( array(
                    'prev_text' => '&laquo; 前のページ',
                    'next_text' => '次のページ &raquo;',
                ) ); ?>
            </div>

        <?php else : ?>

            <p class="no-posts">投稿がまだありません。</p>

        <?php endif; ?>

    </div>
</main>

<?php get_footer(); ?>

2.2 よく使うWordPressの投稿関連関数

関数出力内容
have_posts()表示する投稿があるか確認する(true / false
the_post()ループの中で現在の投稿データを準備する
the_ID()投稿のIDを出力する
the_title()投稿のタイトルを出力する
the_permalink()投稿のURLを出力する
the_excerpt()投稿の抜粋を出力する
the_date()投稿日を出力する
get_the_date()投稿日を文字列で返す(echo が必要)
the_category()カテゴリー名を出力する
has_post_thumbnail()アイキャッチ画像があるか確認する
the_post_thumbnail()アイキャッチ画像を出力する

💡 the_○○()get_the_○○() の違いを覚えましょう: 頭に the_ が付く関数はそのまま出力(echo)します。get_the_ が付く関数は値を返すだけなので、使うときは echo get_the_date() のように echo を前に付けます。


3. 個別投稿ページを作る(single.php)

3.1 single.phpを新規作成する

ブログ記事の詳細ページを表示するテンプレートです。

<?php get_header(); ?>

<main class="site-main">
    <div class="container">

        <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

            <article class="single-post" id="post-<?php the_ID(); ?>">

                <header class="single-post__header">

                    <div class="single-post__meta">
                        <time datetime="<?php echo get_the_date( 'Y-m-d' ); ?>">
                            <?php echo get_the_date(); ?>
                        </time>
                        <?php the_category( '・' ); ?>
                    </div>

                    <h1 class="single-post__title">
                        <?php the_title(); ?>
                    </h1>

                    <?php if ( has_post_thumbnail() ) : ?>
                        <div class="single-post__thumb">
                            <?php the_post_thumbnail( 'large' ); ?>
                        </div>
                    <?php endif; ?>

                </header>

                <div class="single-post__content">
                    <?php the_content(); ?>
                </div>

                <footer class="single-post__footer">
                    <!-- 前後の投稿へのリンク -->
                    <nav class="post-navigation">
                        <div class="nav-previous">
                            <?php previous_post_link( '%link', '&laquo; %title' ); ?>
                        </div>
                        <div class="nav-next">
                            <?php next_post_link( '%link', '%title &raquo;' ); ?>
                        </div>
                    </nav>
                </footer>

            </article>

        <?php endwhile; endif; ?>

    </div>
</main>

<?php get_footer(); ?>

4. 固定ページを作る(page.php)

4.1 page.phpを新規作成する

「About」「お問い合わせ」「プライバシーポリシー」などの固定ページ用テンプレートです。

<?php get_header(); ?>

<main class="site-main">
    <div class="container">

        <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

            <article class="page-content" id="page-<?php the_ID(); ?>">

                <header class="page-content__header">
                    <h1 class="page-content__title">
                        <?php the_title(); ?>
                    </h1>
                </header>

                <?php if ( has_post_thumbnail() ) : ?>
                    <div class="page-content__thumb">
                        <?php the_post_thumbnail( 'full' ); ?>
                    </div>
                <?php endif; ?>

                <div class="page-content__body">
                    <?php the_content(); ?>
                </div>

            </article>

        <?php endwhile; endif; ?>

    </div>
</main>

<?php get_footer(); ?>

4.2 固定ページ専用のテンプレートを作る

固定ページの中でも「お問い合わせページだけ特別なレイアウトにしたい」という場合は、専用のテンプレートファイルを作れます。

<?php
/*
 * Template Name: お問い合わせページ
 * Description: お問い合わせフォーム専用のテンプレート
 */
?>

<?php get_header(); ?>

<main class="site-main contact-page">
    <div class="container">
        <h1>お問い合わせ</h1>

        <!-- Contact Form 7 のショートコードなどを配置 -->
        <div class="contact-form">
            <?php the_content(); ?>
        </div>

    </div>
</main>

<?php get_footer(); ?>

このファイルを page-contact.php などの名前でテーマフォルダに保存すると、管理画面の固定ページ編集画面で「テンプレート」として選択できるようになります。

💡 コメントの Template Name: が重要です: このコメントがないとWordPressはカスタムテンプレートとして認識しません。ファイル名は自由ですが先頭に page- をつけるのが一般的な慣習です。


5. functions.phpの基本

5.1 functions.phpとは

functions.php はWordPressテーマの「設定ファイル」のような役割を持つPHPファイルです。テーマフォルダの直下に置くことで、WordPressが自動的に読み込みます。

my-portfolio-theme/
├── index.php
├── style.css
├── functions.php  ← 新規作成する
├── header.php
├── footer.php
└── ...

⚠️ functions.php の先頭に <?php タグだけを書いて終了タグ ?> は書かないのがWordPressの慣例です: 終了タグの後に余分な空白や改行が入るとエラーの原因になるため、PHPファイルはできるだけ終了タグを省略します。

5.2 CSSとJavaScriptを正しく読み込む(wp_enqueue_scripts)

前回のやり方では header.php に直接 <link> タグや <script> タグを書きました。WordPressでは wp_enqueue_scripts というフックを使って functions.php から読み込む方法が推奨されています。

<?php

function my_theme_enqueue_assets() {

    // テーマのCSSを読み込む
    wp_enqueue_style(
        'my-reset-style',              // 識別名(ユニークな名前)
        get_template_directory_uri() . '/css/reset.css',  // ファイルのURL
        array(),                       // 依存するスタイルシートの識別名
        '1.0.0'                        // バージョン番号(キャッシュ対策)
    );

    wp_enqueue_style(
        'my-main-style',
        get_template_directory_uri() . '/css/style.css',
        array( 'my-reset-style' ),    // reset.cssの後に読み込む
        '1.0.0'
    );

    // JavaScriptを読み込む
    wp_enqueue_script(
        'my-main-script',              // 識別名
        get_template_directory_uri() . '/js/main.js',  // ファイルのURL
        array( 'jquery' ),             // 依存するスクリプト(jQueryなど)
        '1.0.0',                       // バージョン番号
        true                           // true = </body>の前に読み込む
    );
}

add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_assets' );

💡 この方法を使うメリットはいくつかあります:

  • 同じCSSが重複して読み込まれるのを防ぐ
  • プラグインが同じjQueryを二重に読み込まないよう管理できる
  • バージョン番号でキャッシュのコントロールができる

5.3 テーマサポートを有効にする(add_theme_support)

WordPressの標準機能(アイキャッチ画像・ナビゲーションメニューなど)を使えるようにするには add_theme_support() で機能を有効化します。

function my_theme_setup() {

    // アイキャッチ画像(サムネイル)を有効化する
    add_theme_support( 'post-thumbnails' );

    // カスタム画像サイズを登録する
    add_image_size( 'my-card-thumb', 640, 360, true );  // 横640px・縦360px・トリミングあり

    // タイトルタグをWordPressに管理させる
    add_theme_support( 'title-tag' );

    // ブロックエディターのスタイルを有効化する
    add_theme_support( 'wp-block-styles' );

    // HTML5のマークアップに対応する
    add_theme_support( 'html5', array(
        'search-form',
        'comment-form',
        'comment-list',
        'gallery',
        'caption',
    ) );
}

add_action( 'after_setup_theme', 'my_theme_setup' );

⚠️ アイキャッチ画像を使うには add_theme_support('post-thumbnails') が必要です: この記述がないと管理画面の投稿編集画面にアイキャッチ画像の設定欄が表示されません。前回のコードで has_post_thumbnail() を使う場合は必ず有効化しておきましょう。

5.4 カスタムナビゲーションメニューを登録する

管理画面からメニューを設定できるようにするには register_nav_menus() で登録します。

function my_theme_setup() {

    // ...(上記のコードに追記する)

    // ナビゲーションメニューの場所を登録する
    register_nav_menus( array(
        'global-nav' => 'グローバルナビゲーション',
        'footer-nav' => 'フッターナビゲーション',
    ) );
}

header.php の中でメニューを表示する際は以下のように書きます。

<nav class="global-nav">
    <?php wp_nav_menu( array(
        'theme_location' => 'global-nav',  // 登録したメニューの場所のキー
        'container'      => false,         // メニューを囲むコンテナを出力しない
        'menu_class'     => 'nav-list',    // ulタグに付けるクラス名
    ) ); ?>
</nav>

5.5 抜粋の文字数を変更する

the_excerpt() が出力する抜粋のデフォルト文字数(英語で55語・日本語では約110文字)を変更できます。

// 抜粋の文字数を変更する(日本語は文字数で指定)
function my_theme_excerpt_length( $length ) {
    return 80;  // 80文字に変更する
}
add_filter( 'excerpt_length', 'my_theme_excerpt_length' );

// 抜粋の末尾の「...」を変更する
function my_theme_excerpt_more( $more ) {
    return '…';
}
add_filter( 'excerpt_more', 'my_theme_excerpt_more' );

5.6 管理バーをフロント側に表示しないようにする

ログイン中のユーザーがサイトを見るときに表示される黒い管理バーを非表示にできます。

// 管理バーをフロント側で非表示にする
add_filter( 'show_admin_bar', '__return_false' );

6. 完成したfunctions.phpの全体像

<?php

// ===== テーマのセットアップ =====
function my_theme_setup() {

    // アイキャッチ画像を有効化する
    add_theme_support( 'post-thumbnails' );
    add_image_size( 'my-card-thumb', 640, 360, true );

    // タイトルタグをWordPressに管理させる
    add_theme_support( 'title-tag' );

    // HTML5対応
    add_theme_support( 'html5', array(
        'search-form', 'comment-form',
        'comment-list', 'gallery', 'caption',
    ) );

    // ナビゲーションメニューを登録する
    register_nav_menus( array(
        'global-nav' => 'グローバルナビゲーション',
        'footer-nav' => 'フッターナビゲーション',
    ) );
}
add_action( 'after_setup_theme', 'my_theme_setup' );


// ===== CSS・JavaScriptの読み込み =====
function my_theme_enqueue_assets() {

    wp_enqueue_style(
        'my-reset-style',
        get_template_directory_uri() . '/css/reset.css',
        array(),
        '1.0.0'
    );

    wp_enqueue_style(
        'my-main-style',
        get_template_directory_uri() . '/css/style.css',
        array( 'my-reset-style' ),
        '1.0.0'
    );

    wp_enqueue_script(
        'my-main-script',
        get_template_directory_uri() . '/js/main.js',
        array(),
        '1.0.0',
        true
    );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_assets' );


// ===== 抜粋の設定 =====
function my_theme_excerpt_length( $length ) {
    return 80;
}
add_filter( 'excerpt_length', 'my_theme_excerpt_length' );

function my_theme_excerpt_more( $more ) {
    return '…';
}
add_filter( 'excerpt_more', 'my_theme_excerpt_more' );


// ===== 管理バーを非表示にする =====
add_filter( 'show_admin_bar', '__return_false' );

7. 現時点のテーマフォルダ構成

my-portfolio-theme/
├── index.php        ← トップページ(フォールバック)
├── home.php         ← ブログ投稿一覧  【今回追加】
├── single.php       ← 個別投稿ページ  【今回追加】
├── page.php         ← 固定ページ      【今回追加】
├── functions.php    ← テーマ設定      【今回追加】
├── style.css        ← テーマ情報
├── header.php
├── footer.php
├── sidebar.php
├── css/
│   ├── reset.css
│   └── style.css
├── js/
│   └── main.js
└── images/
    └── (画像ファイル群)

8. 動作確認チェックリスト

home.php を作成して投稿一覧が表示されるか確認したか

single.php を作成して個別投稿ページが表示されるか確認したか

page.php を作成して固定ページが表示されるか確認したか

functions.php を作成してエラーが出ていないか確認したか

add_theme_support('post-thumbnails') を追加してアイキャッチ画像欄が表示されるか確認したか

wp_enqueue_style() に切り替えてCSSが正しく読み込まれているか確認したか

管理画面で「外観」→「メニュー」を開いてナビゲーションメニューの場所が登録されているか確認したか

Chrome DevToolsのコンソールにエラーが出ていないか確認したか


まとめ

今回はWordPressオリジナルテーマ開発の第2弾として、投稿一覧・個別投稿・固定ページのテンプレートファイルの作り方と functions.php の基本を解説しました。ポイントをまとめると:

  • WordPressはURLに応じてテンプレートファイルを自動で選択する(テンプレート階層)
  • home.php で投稿一覧・single.php で個別投稿・page.php で固定ページを表示する
  • have_posts()the_post() を使ったループでWordPressの投稿データを取り出す
  • 固定ページに専用テンプレートを割り当てるにはファイル先頭に Template Name: を書く
  • functions.php はテーマの設定ファイルで add_action()add_filter() を使って機能を追加する
  • CSSとJavaScriptは header.php に直書きするより wp_enqueue_scripts フックで管理する方が安全
  • add_theme_support('post-thumbnails') がないとアイキャッチ画像が使えない

次の記事では、WordPressのカスタム投稿タイプを使って制作実績(Works)などのオリジナルコンテンツを管理する方法を解説します。お楽しみに!

コメント

タイトルとURLをコピーしました