初心者向けWordPressのPHP|テンプレート編
この記事でわかること
- ページを表示するために使うPHPの全体像をつかめる
- テンプレートファイルのどの部分が何をしているのか、読み取れるようになる
WordPressのテーマを自作しようとすると、ファイルや関数の多さに戸惑いがちです。この記事では、「お知らせ」の一覧ページを例に、ページを表示するファイルに書くPHPを読み解いていきます。PHPのファイルで作る「クラシックテーマ」が前提です。
関数を全部覚える必要はないよ!「このかたまりは何をしているのか」がわかれば十分だね
テンプレートに書くPHPの全体像
WordPressのページは、ページごとの中身を書くファイルが、上下の共通部分を読み込んで作られます。この記事では、この3種類のファイルに書くPHPを扱います。
ページごとの中身を書く。投稿のタイトルや本文もここで表示する
get_header()上の共通部分を読み込む
get_footer()下の共通部分を読み込む
ページの上の共通部分
ページの下の共通部分
中身を書くテンプレートファイルは、役割ごとのかたまり(ブロック)が上から並んでいます。この記事では、会社サイトの「お知らせ」の一覧ページを例に、次の5つのブロックを扱います。
ヘッダーを表示する
件数ぶん、下の③④を繰り返す
次のページへのリンクを表示する
フッターを表示する
5つをつなげたコードの全文は、記事の最後の「完成形のコード」にまとめています。
この後は、コードを読むための前提、5つのブロックの解説、表示を工夫するための機能の順に並んでいます。前提の内容はどのブロックにも関わるため、初めての人は上から読み進めてください。知りたい内容が決まっている場合は、サイドバー(スマホは右下のボタン)の「目的から探す」から移動できます。
テーマに機能を追加するPHPは、「functions.phpの書き方」で紹介しています。
読む前に知っておくこと
ブロックを読む前に、PHPの書き方と、テーマのファイルに共通する決まりを押さえます。
PHPの書き方
テンプレートファイルでは、HTMLの中にPHPを埋め込んで書きます。
| 書き方 | 役割 |
|---|---|
| <?php 〜 ?> | この中に書いた部分だけが、PHPとして実行される |
| echo | 値を画面に出力する |
| <?= 〜 ?> | <?php echo 〜 ?> を短く書いたもの |
| if 〜 endif | 条件に合うときだけ、間のHTMLを表示する |
| while 〜 endwhile | 条件に合う間、間のHTMLを繰り返し表示する |
<?php if ( 条件 ) : ?> <!-- 条件に合うときだけ -->
<p>ここが表示される</p>
<?php endif; ?> <!-- ifの終わり -->
HTMLの中に「ここだけPHPだよ」と目印を付けるイメージだね!
どのファイルが使われるかを知る
テンプレート階層は、表示するページの種類に応じて、使うテンプレートファイルをWordPressが自動で選ぶ仕組みです。
| ページの種類 | 専用のファイル | 共通のファイル |
|---|---|---|
| 固定ページ | page-{スラッグ}.php | page.php |
| 個別の投稿 | single-{投稿タイプ}.php | single.php |
| カテゴリの一覧 | category-{スラッグ}.php | category.php |
| 検索結果 | なし | search.php |
| 404ページ | なし | 404.php |
ファイルは、スラッグ※1などを名前に含む専用のものから順に探されます。例えば固定ページでは、次の順番です。
スラッグが一致するページだけで使われる
IDが一致するページだけで使われる
最後の候補。どのファイルもなければ、必ずこれが使われる
この記事で例にする「お知らせ」の一覧ページでは、archive-news.php というファイルが使われます。news は、お知らせの投稿タイプの名前です。
「このページだけデザインを変えたい」ときは、専用のファイルを作ればいいんだね!
※1:スラッグ…ページのURLに使われる、ページごとの名前。
書き忘れると困るコードを入れる
header.php と footer.php には、WordPressやプラグインが出力を差し込むための関数を書きます。
| 関数 | 役割 |
|---|---|
| wp_head() | head の中に、CSS・JSなどを出力する |
| body_class() | 表示中のページに応じたclassを、body に付ける |
| wp_body_open() | body の開始直後に、出力を差し込めるようにする |
| wp_footer() | body の閉じタグの前に、JSなどを出力する |
header.php
<head>
<?php wp_head(); ?> <!-- ① -->
</head>
<body <?php body_class(); ?>> <!-- ② -->
<?php wp_body_open(); ?> <!-- ③ -->
| コード解説 | |
|---|---|
| ① | headの閉じタグの前に書く |
| ② | bodyの開始タグの中に書く |
| ③ | bodyの開始タグの直後に書く |
footer.php
<?php wp_footer(); ?> <!-- bodyの閉じタグの前に書く -->
</body>
wp_head() と wp_footer() がないと、CSS・JSやプラグインの出力がページに差し込まれません。wp_body_open() は、WordPress 5.2で追加された関数です。
「CSSが効かない!」と焦ったら、まずこの2つがあるか確認してみてね
不正な入力からサイトを守る
エスケープは、出力するデータから不正なHTMLやscriptタグなどを取り除き、安全に表示する処理です。公式の推奨は「出力する直前にエスケープする」ことです。
| 関数 | 使う場所 |
|---|---|
| esc_html() | HTML要素で囲まれたテキスト |
| esc_attr() | class・alt などの属性値 |
| esc_url() | href・src を含む、すべてのURL |
| wp_kses_post() | HTMLを残したまま出力したい内容 |
<p><?php echo esc_html( $text ); ?></p> <!-- テキスト -->
<img alt="<?php echo esc_attr( $alt ); ?>"> <!-- 属性値 -->
<a href="<?php echo esc_url( $link ); ?>">link</a> <!-- URL -->
どの関数にするか迷ったら、「どこに出力するか」で選んでみてね!
5つのブロックを順に読む
ここからは、「お知らせ」の一覧ページ(archive-news.php)を、全体像の図の①〜⑤の順に読んでいきます。
共通パーツを読み込む
ヘッダーやフッターは、どのページでも同じ内容です。ページごとに書くと修正が大変なので、別のファイルに分けて、各テンプレートファイルから読み込みます。
<?php get_header(); ?> <!-- 上の共通部分を読み込む -->
<main>
</main>
<?php get_footer(); ?> <!-- 下の共通部分を読み込む -->
このブロックを書くと、header.php と footer.php の中身が、書いた位置に差し込まれます。ページの中身は、間の main の中に書いていきます。
| 関数 | 読み込むもの |
|---|---|
| get_header() | header.php |
| get_footer() | footer.php |
| get_sidebar() | sidebar.php |
| get_template_part() | それ以外の共通パーツ |
get_template_part() は、読み込むパーツに値を渡すこともできます(WordPress 5.5以降)。
ヘッダーを直したいときも1ファイルで済むから、後の修正がラクになるよ!
記事一覧を表示する
一覧ページには、複数のお知らせが並びます。ループは、表示する投稿を1件ずつ取り出して、同じHTMLを繰り返し出力する仕組みです。
<?php if ( have_posts() ) : ?> <!-- ① -->
<?php while ( have_posts() ) : ?> <!-- ② -->
<?php the_post(); ?> <!-- ③ -->
<h2><?php the_title(); ?></h2>
<?php endwhile; ?>
<?php endif; ?>
| コード解説 | |
|---|---|
| ① | 表示する投稿があるときだけ、中の処理を行う |
| ② | 投稿が残っている間、繰り返す |
| ③ | 次の投稿を取り出して、表示できる状態にする |
このブロックを書くと、お知らせの件数ぶん、間に書いたHTMLが繰り返し出力されます。上の例では、タイトルの見出しがお知らせの数だけ並びます。
| 関数・クラス | 役割 |
|---|---|
| have_posts() | 表示する投稿が残っているか判定する |
| the_post() | 次の投稿を取り出す |
| new WP_Query() | 別の条件で投稿を取得する |
| wp_reset_postdata() | 投稿データを元に戻す |
ページ本来の投稿を表示するのがメインループ、WP_Query というクラス※2で別の投稿を並べるのがサブループです。サブループの後は、wp_reset_postdata() で元に戻します。
古い解説で見かける query_posts() は、公式が「避けるべき」としている書き方です。
新着記事を並べたあとで表示がおかしくなったら、元に戻し忘れを疑ってみてね
※2:クラス…関連するデータと処理をひとまとめにした設計図のようなもの。new を付けて使います。
タイトルや本文を表示する
ループで取り出したお知らせの、タイトルや日付を表示します。テンプレートタグは、データベースから記事の情報を取り出して表示する関数です。
<time><?php the_time( 'Y.m.d' ); ?></time> <!-- ① -->
<h2>
<a href="<?php the_permalink(); ?>"> <!-- ② -->
<?php the_title(); ?> <!-- ③ -->
</a>
</h2>
<?php the_excerpt(); ?> <!-- ④ -->
| コード解説 | |
|---|---|
| ① | 投稿の日付を、指定した形式で表示する |
| ② | 投稿のURLを出力して、個別ページへのリンクにする |
| ③ | 投稿のタイトルを表示する |
| ④ | 投稿の抜粋を表示する |
このブロックを書くと、お知らせ1件ごとに、日付・リンク付きのタイトル・抜粋が表示されます。テンプレートタグの多くは、ループの中に書かないと正しく表示されません。
| 関数 | 表示するもの |
|---|---|
| the_title() | 投稿のタイトル |
| the_content() | 投稿の本文 |
| the_excerpt() | 投稿の抜粋 |
| the_permalink() | 投稿のURL |
| the_category() | 投稿のカテゴリ |
| the_time() | 投稿の日時 |
| bloginfo(‘name’) | サイト名 |
「the_」で始まる関数は、書いた場所にそのまま表示されるものが多いよ!
アイキャッチ画像を表示する
お知らせごとの画像を表示します。アイキャッチ画像は設定されていない投稿もあるため、あるかどうかを確かめてから表示します。
<?php if ( has_post_thumbnail() ) : ?> <!-- 設定されているか確認 -->
<?php the_post_thumbnail( 'medium' ); ?> <!-- サイズを指定して表示 -->
<?php endif; ?>
このブロックを書くと、アイキャッチ画像が設定されたお知らせにだけ、画像が表示されます。
| 関数 | 役割 |
|---|---|
| has_post_thumbnail() | アイキャッチ画像が設定されているか判定する |
| the_post_thumbnail() | アイキャッチ画像を表示する |
| get_the_post_thumbnail() | 表示せずに、値を返す※3 |
アイキャッチ画像を使うには、先に functions.php で機能を有効にしておく必要があります。有効にしないと、投稿の編集画面に設定欄が表示されません。
画像がない記事もあるから、表示する前に確認しておくと安心だよ!
※3:値を返す…画面には出力せず、取得した結果を変数などに受け取れる形で渡すこと。
ページ送りを付ける
お知らせが増えると、1ページに収まらなくなります。ページネーションは、一覧を複数のページに分けて、前後へ移動できるようにする仕組みです。
<?php endwhile; ?>
<?php the_posts_pagination(); ?> <!-- ループの後に書く -->
このブロックを書くと、一覧の下に番号付きのページ送りが表示されます。1ページの件数は、管理画面の「設定」→「表示設定」で決まり、初期値は10件です。お知らせだけ件数を変える方法は、「functions.phpの書き方」で紹介しています。
| 関数 | 使うページ | 表示するもの |
|---|---|---|
| the_posts_pagination() | 一覧ページ | 番号付きのページ送り |
| next_posts_link() | 一覧ページ | 次のページへのリンク |
| previous_posts_link() | 一覧ページ | 前のページへのリンク |
| next_post_link() | 個別の投稿 | 次の記事へのリンク |
| previous_post_link() | 個別の投稿 | 前の記事へのリンク |
「posts」は一覧ページ用、「post」は個別の記事用。sがあるかないかで見分けてね!
さらに表示を工夫する
5つのブロックに慣れたら、サイトに合わせて次のような表示を足していきます。ここでは紹介にとどめます。
入力欄の値を表示する
カスタムフィールドは、投稿に独自の入力項目を追加して、その値を表示する仕組みです。
| 関数 | 提供元 | 使う場面 |
|---|---|---|
| get_post_meta() | WordPress標準 | プラグインを使わずに値を取得するとき |
| get_field() | ACF(Advanced Custom Fields)プラグイン | ACFで作った入力項目の値を取得するとき |
get_field() はWordPress本体ではなく、ACFプラグインの関数です。どちらの関数で取得した値も、出力する前にエスケープが必要です。
コピペしたコードが動かないときは、ACFが入っているか確認してみてね!
ページごとに表示を変える
条件分岐タグは、表示中のページを判定して true/false※4 を返す関数で、if と組み合わせて使います。
| 関数 | 判定する内容 |
|---|---|
| is_front_page() | サイトのトップページか |
| is_home() | 投稿の一覧ページか |
| is_single() | 個別の投稿か |
| is_page() | 固定ページか |
| is_singular() | 個別の投稿か、固定ページか |
| is_archive() | カテゴリや日付などの一覧ページか |
| is_search() | 検索結果ページか |
| is_404() | 404ページか |
条件分岐タグは、functions.php に直接書いても動きません。functions.php は、表示するページが決まる前に読み込まれるためです。テンプレートファイルの中か、フックの中で使います。
「トップページだけ〇〇したい」と思ったら、条件分岐タグの出番だよ!
※4:true/false…判定の結果を表す値。条件に当てはまれば true、当てはまらなければ false になります。
メニューを表示する
管理画面の「外観」→「メニュー」で作ったメニューを、header.php などに表示します。
| 書き方 | 役割 |
|---|---|
| wp_nav_menu() | 登録したメニューを表示する |
| ‘theme_location’ | どの位置のメニューを表示するかを指定する |
メニューを表示するには、先に functions.php でメニューの位置を登録しておく必要があります。
メニューを管理画面から直せるようにしておくと、更新する人に喜ばれるよ!
ウィジェットを表示する
ウィジェット※5を置けるエリアを、sidebar.php などに表示します。
| 関数 | 役割 |
|---|---|
| dynamic_sidebar() | 登録したウィジェットエリアを表示する |
| is_active_sidebar() | エリアにウィジェットが入っているか判定する |
| get_sidebar() | sidebar.php を読み込む |
ウィジェットエリアも、先に functions.php で登録しておく必要があります。
名前は「サイドバー」だけど、フッターなど好きな場所に置けるよ!
※5:ウィジェット…新着記事や検索フォームなど、管理画面から追加できる部品。
検索結果ページを作る
サイト内検索のフォームと、検索結果のページを用意します。
| 関数・ファイル | 役割 |
|---|---|
| get_search_form() | 検索フォームを表示する |
| is_search() | 検索結果ページか判定する |
| search.php | 検索結果ページで使われるテンプレートファイル |
search.php がない場合は、index.php が使われます。検索結果だけ見た目を変えたいときは、search.php を作ります。
検索結果の一覧も、記事一覧と同じループで表示できるよ!
完成形のコード
5つのブロックをつなげると、次の archive-news.php になります。
<?php get_header(); ?> <!-- ① -->
<main>
<?php if ( have_posts() ) : ?> <!-- ② -->
<?php while ( have_posts() ) : ?>
<?php the_post(); ?>
<article>
<time> <!-- ③ -->
<?php the_time( 'Y.m.d' ); ?>
</time>
<h2>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h2>
<?php the_excerpt(); ?>
<?php if ( has_post_thumbnail() ) : ?> <!-- ④ -->
<?php the_post_thumbnail( 'medium' ); ?>
<?php endif; ?>
</article>
<?php endwhile; ?>
<?php the_posts_pagination(); ?> <!-- ⑤ -->
<?php endif; ?>
</main>
<?php get_footer(); ?> <!-- ① -->
| コード解説 | |
|---|---|
| ① | 上下の共通部分を読み込む(共通パーツを読み込む) |
| ② | お知らせを1件ずつ取り出して繰り返す(記事一覧を表示する) |
| ③ | 日付・タイトル・抜粋を表示する(タイトルや本文を表示する) |
| ④ | 画像があるときだけ表示する(アイキャッチ画像を表示する) |
| ⑤ | 一覧の下にページ送りを付ける(ページ送りを付ける) |
「お知らせ」という投稿の種類そのものは、functions.php で登録します。登録の方法は、「functions.phpの書き方」で紹介しています。
さいごに
まとめ
テンプレートファイルは、役割ごとのブロックが並んだファイルです。共通パーツを読み込み、ループで投稿を取り出し、その中でタイトルや画像を表示する、という形はどのページでも同じです。
最初に押さえる3つのポイント
- header.php・footer.php には、wp_head() などの関数を書く
- 投稿は、ループの中でテンプレートタグを使って表示する
- データを出力するときは、場所に合わせてエスケープする
ほかのテーマのテンプレートファイルを見るときも、「このブロックは何をしているか」を探しながら読んでみてください。
よくある質問
自作テーマでCSSやプラグインの機能が反映されません
header.php に wp_head()、footer.php に wp_footer() が書かれているか確認しましょう。この2つがないと、CSS・JSやプラグインの出力がページに差し込まれません。
書く位置は「書き忘れると困るコードを入れる」で解説しています。
新着記事を並べた後、ページの表示がおかしくなりました
WP_Query で別の投稿を並べた後は、wp_reset_postdata() で投稿データを元に戻す必要があります。戻し忘れると、その後の表示に別の投稿のデータが使われます。
ループの書き方は「記事一覧を表示する」で解説しています。
get_field() はWordPressの標準の関数ですか?
いいえ。get_field() はACF(Advanced Custom Fields)プラグインの関数です。プラグインを使わない場合は、WordPress標準の get_post_meta() を使います。
使い分けは「入力欄の値を表示する」で解説しています。
エスケープはいつすればいいですか?
公式の推奨は、出力する直前です。出力する場所に合わせて、テキストには esc_html()、属性値には esc_attr()、URLには esc_url() を使います。
使い分けは「不正な入力からサイトを守る」で解説しています。
functions.php に条件分岐タグを書いたのに動きません
functions.php は、表示するページが決まる前に読み込まれます。そのため、条件分岐タグを直接書いても判定できません。テンプレートファイルの中か、フックの中で使いましょう。
条件分岐タグの種類は「ページごとに表示を変える」で解説しています。

