投稿用テンプレートsingle.phpを作る(WordPressループの使い方)[WordPressテーマ作成の手順9]

今回は投稿用のテンプレート「single.php」を作る。 WordPressのテーマ作成8で、トップページの表示用のテンプレート「home.php」を作ったところからの続きです。
手順は、「home.php」をコピーして「single.php」にし、投稿記事を表示する部分をパーツテンプレート「content.php」にする。加えて前後の記事にリンクするナビも作成する。

WordPressの管理画面で書いた投稿記事は、データベースに蓄えられ、このテンプレート「single.php」に出力されてブラウザに表示される。
「single.php」では、記事を出力するためにループを使う。WordPressのループは、投稿・固定ページ・アーカイブページ用など、ほとんどのテンプレートで使う大事なPHPソース。
ループ(loop)というだけあって、繰り返し処理をしてくれる。
WordPressを使うなら、ループの概念を知っておかないと、というほど重要。

本日のINDEX

スポンサーリンク

home.phpをコピーしてsingle.phpを作る

前回作ったhome.phpをコピーし、ファイル名をsingle.phpに変更。
このsingle.phpという名のファイルがあれば、WordPressは投稿用ページとして表示する。

投稿用のテンプレートについて

WordPressは、投稿記事はsingle.phpで表示する。これが無ければindex.phpが使われる。

ちなみに「カスタム投稿タイプ」を使った場合は single-[posttype].php([posttype]は任意の名前をつける)が最優先のテンプレートになる。
(例えば、shopというカスタム投稿タイプに、single-shop.phpというテンプレートを作ればそれが適用される)
single- [posttype].phpが無ければsingle.php、どちらも無ければindex.phpが使われる。

テンプレートの種類と優先順位についてはこちら:
WordPress「テンプレート」の優先順位 | 超初心者のサーバー移転とドメイン移管&ついでにWordPressも!

「カスタム投稿タイプ」とは…
WordPressは、デフォルトで2つの投稿タイプ(post_type)がある。
・投稿(ブログのような、時系列で並べたりカテゴリやタグで分類できる記事。post_typeは「post」)
・固定ページ(カテゴリやタグは付けられない。ページの親子関係を指定できる。post_typeは「page」)
コレら以外に、自分で好きな投稿タイプを追加できる。それがカスタム投稿タイプ。post_typeは「好きな名前」
★例えば、ショップとか製品情報など、違うテンプレートで表示したいモノがある時に使うと便利。
★テンプレートでの表示でなく、固定ページの中にパーツとして表示する事もできる。
★「カスタム投稿タイプ」は、カテゴリやタグで分類できないが「カスタムタクソノミー」で分類できる。また、時系列で並べられるし、ページの親子関係も指定できる。

「カスタムタクソノミー」とは…
WordPressにデフォルトで備わっている「カテゴリ」「タグ」のような分類を、自分で好きな名前で追加できる。これがカスタムタクソノミー
★「カスタムタクソノミー」は、固定ページや投稿など全てのポストタイプに使える(どれか1つにヒモ付けされる)。

★「カスタム投稿タイプ」「カスタムタクソノミー」は、プラグイン Custom Post Type UI で簡単に追加できる。

記事の本文部分をループにする

home.phpをコピーし、ファイル名をsingle.phpに変更したら、
single.php内のメインコンテンツ部分に投稿記事を表示するわけなので、ここを編集。
(この他のheader, sidebar, footerはパーツテンプレートに分割済み)

ここに便利なWordPressの「ループ」を仕込んで、管理画面で書いた投稿記事を表示させる。

ループの基本形

ループは、該当する記事があれば、あるだけ表示するという繰り返し処理のPHPソース。
シンプルなのにオートマティックなWordPressの仕様です。
single.phpの場合は、該当する記事は1コなので、1回しか繰り返さないけど、
アーカイブページ(カテゴリやタグの一覧ページとか)なら、該当する記事をあるだけ表示する。

ループの基本形はこんなかんじ。

<?php
if (have_posts()) :  //もしも該当する記事があれば、
  while (have_posts()) :  //記事があるだけ
    the_post(); //記事を表示する

//★ここに記事を表示する部分のソースを書く

  endwhile; //whileを終了
else:

//★ここに投稿がない場合の表示ソースを書く

endif; //ループを終了
?>

記事を表示する部分を書いた具体例は、ざっとこんなかんじ。

<?php
if (have_posts()) : while (have_posts()) : the_post();
//例えば下記のように、カテゴリによってdivのクラス名を変えたりできる
//投稿がカテゴリ「1」に属していれば、CSSクラス"post-cat-one"のdivを、
//それ以外なら、CSSクラス"post"のdivを表示
      if (in_category('1')) { ?>
      <div class="post-cat-one">
      <?php } else{ ?>
      <div class="post">
      <?php } ?>
//タイトルとパーマリンクを表示
        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
//日時を表示
        <small><?php the_time('Y年n月j日'); ?></small>
//カテゴリをカンマ区切りで表示
        <p class="postmetadata"><?php the_category(', '); ?></p>
//投稿本文を表示
        <div class="entry"><?php the_content(); ?></div>
        </div> //最初のdiv(クラス名post-cat-oneかpost)を閉じ
<?php endwhile; else: ?> //whileを終了し、投稿がないなら以下を表示
      <p>記事が見つかりませんでした。</p>
<?php endif; ?>

記事本文を出力するテンプレートタグは「the_content()(上のソースの18行目)。
管理画面で書いた記事は、このテンプレートタグでそっくりそのまま出力される。

上のソースはWordPress公式codexを参考にしました:ループ-WordPress Codex 日本語版

ループにパーツテンプレートを埋め込む

上のソースのように、ループのソース内に投稿記事表示用のソースを書いても良いが、
レイアウトのためのdivやp, imgなどを仕込むと、ソースが長く複雑になってしまう。
そこで、投稿記事表示部分だけ「パーツテンプレート」にして埋め込むほうが、スッキリするし、あとの編集が楽だ。
このブログでは「content.php」を別に作って埋め込むことにした。

<?php
if (have_posts()) : 
  while (have_posts()) :
    the_post();
    get_template_part('content');
  endwhile;
endif;
?>

elseは省略。投稿記事が「無い」ってことは無いから。
(single.phpは投稿記事の表示だけだから。アーカイブや検索結果でループを使う時は elseは必要)

パーツテンプレートに関してはこちら:
index.phpをパーツテンプレートに分割する [WordPressテーマ作成の手順3] | *Web Design 覚え書き*

パーツテンプレートcontent.phpを作る

パーツテンプレートcontent.phpを作っていく。
まず、1番最初にHTMLファイルを作った中の、投稿ページ用レイアウト「single.html」をコピーして「content.php」という名前に書き換える。
このファイルの、投稿記事表示部分以外を全部削除する。
single.phpで記述する外側のボックス(<article>〜</article>など)が重複しないように、その中に入るモノだけ残す
要するに、上のソースの5行目「get_template_part(‘content’);」のところに入れたいものだけを残すのね。

あとは、記事の日付・カテゴリ・タイトル・アイキャッチ画像・本文などを「テンプレートタグ」に書き換えるだけでOK。(最初にキチンと投稿用のレイアウト(single.html)を作っておけば、CSS指定も済んでおり、コレだけでOKなわけ。何事も最初の計画が肝心ですw)

<div class="col-full">
  <div class="wrap-col">
    <article class="postBox">
     <div class="metaData clearfix">
     <p id="iconDate"><img src="<?php bloginfo('template_url');?>/images/icon_dat_wht.png"/><?php the_time('Y年n月j日'); ?></p>
     <p id="iconCat"><img src="<?php bloginfo('template_url');?>/images/icon_cat_wht.png"/><?php $cat = get_the_category(); $cat = $cat[0]; $cat_name = $cat->cat_name; echo $cat_name; ?></p>
     </div><!-- ^ .metaData END-->
     <div class="entry_heading clearfix">
     <div class="col-1-3"><?php the_post_thumbnail(); ?></div>
     <div class="col-2-3"><h1><?php the_title();?></h1></div>
     </div><!-- ^ .entry_heading END-->
     <div class="entry_body"><?php the_content();?></div>
     <div class="entry_body_bottom"></div>
    </article><!-- ^ .postBox END-->
  </div><!-- ^ .wrap-col END-->
</div><!-- ^ .col-full END-->

それぞれの「テンプレートタグ」は、home.phpを作った時のモノとほぼ同じ。
(参考:トップページ用テンプレートhome.phpを作る [WordPressテーマ作成の手順8]
もちろん、レイアウトはCSSで大幅に変えている。

1つだけ、home.phpと違うテンプレートタグは、
抜粋記事のテンプレートタグ(the_excerpt())ではなく、
記事本文表示のテンプレートタグ(the_content())を使っていること(12行目)。

なお、上記ソースの div.col-full, div.wrap-col(1〜2と15〜16行目)は、本ブログのグリッドシステムのため。

投稿ページ間のリンクを表示する

content.phpができたので、single.phpで投稿記事が表示できるようになった。
ここでもう1つ、WordPressには投稿記事の「隣接記事へのリンク」をさせる便利で素敵なテンプレートタグがあるので、content.phpに追加しておく。

previous_post_link()」での記事(時系列的に1つ過去の記事)へ
next_post_link()」での記事(時系列的に1つ未来の記事)へ
リンクする。
「previous = 過去」「next = 未来」ってこと(普通ですな。いつも戸惑うけど…w)
このテンプレートタグは必ずループ内で使う。じゃないと何も起こらない。
(今の状況では、single.phpのループ内に仕込まれているパーツテンプレートcontent.phpに書くからOKというわけ)

*上の図は、この時点で最新記事の表示なので「次の記事(未来の記事)」はまだ無いので空欄になっている。

本ブログの、上の図の部分のソースはこんなかんじ。

<div class="col-full">
  <div class="clearfix"></div>
  <div class="wrap-col">
    <nav class="adjacent_post_links clearfix">
    <div class="col-1-2">
    <div class="previous"><?php previous_post_link('%link', '%title'); ?></div>
    </div><!-- ^ .col-1-2 END-->
    <div class="col-1-2">
    <div class="next"><?php next_post_link('%link', '%title'); ?></div>
    </div><!-- ^ .col-1-2 END-->
    </nav><!-- ^ .adjacent_post_links END-->
  </div><!-- ^ .wrap-col END-->
</div><!-- ^ .col-full END-->

上記ソースの div.col-full, div.wrap-col, div.col-1-2 は、本ブログのグリッドシステムによるものです。

previous_post_link()

previous_post_link() の ()内の引数を省略すると、「アンギュラークウォート (<<) 」が付いたテキスト「<< 前の記事へ」が表示され、そのページへのリンクがつく。コレがデフォルト形。

引数を使って指定する場合、引数は次の5個。「,(カンマ)」で区切って使う。
previous_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy );

  • $format
    リンク部分のフォーマット。デフォルトは ‘%link’ のみ(下の$link(記事タイトル)を表示)。
    ‘<strong>%link</strong>’ ’Go to %link’ '<img src="arrow.png"> %link’ などと指定できる。
  • $link
    リンクのテキスト。デフォルトは ‘%title’ で記事のタイトル。
    ‘1つ前の記事へGO!’ などと好きな文言に指定できる。
  • $in_same_term
    コレだけはBoolean型(trueかfalse)。同じカテゴリーの記事に限定するかどうか。デフォルトは false。
  • $excluded_terms
    表示させたくない(除外する)記事のカテゴリID。複数指定はカンマで区切る(例 ‘1, 5, 15’)
  • $taxonomy
    $in_same_termtrue のときだけ使える。タクソノミーを表示。デフォルトは ‘category’

例えばこんなかんじで使用。

<?php previous_post_link('%link', '%title'); ?>
<?php previous_post_link('%link', 'このカテゴリでの前の記事へ', true, '1,8'); ?>

参考サイト:テンプレートタグ/previous post link-WordPress Codex 日本語版

next_post_link()

next_post_link() の ()内の引数を省略すると、「アンギュラークウォート (>>) 」が付いたテキスト「次の記事へ >>」が表示され、そのページへのリンクがつく。コレがデフォルト形。

あとは、previous_post_link() とまったく同じ仕様。
ただし、「向き」というものがあるので、CSSで右詰めにするとか、見やすい工夫は必要ね。

参考サイト:テンプレートタグ/next post link-WordPress Codex 日本語版

single.phpのその後の経過はコチラ

今回はsingle.phpを初めて作り、記事本文と、投稿ページ間のリンクを作った。
このあと、さらにsingle.phpに
関連記事を表示させる
・コメント欄をつける
・Google広告を表示する
といった追加をして完成させる。(記事をアップ次第、順次リンクを貼っていきます)

関連記事

WordPressの Embedカードのリンクを別ウィンドウで開く(PCのみ。スマホ・タブレットはそのまま)

WordPressの Embedカード(ブログカード)のリンクは、デフォルトでは同ウィンドウで開くようになっていますが、これを別ウィンドウ(別タブ)で開くように [記事を読む]

WordPressの Embedカードのスタイルを編集する方法2つ

前回の記事で、WordPress 4.5 の Embedカード(ブログカード)の「テンプレートの構成」や「HTML要素のクラス名」などを調べました。これを元に、 [記事を読む]

WordPress4.5で Embedカードの PHPファイルの構造がだいぶ変わったみたい

前回から WordPressの Embedカード(ブログカード)について調べたことをメモっています。 今回は Embedカードの PHPファイルの構造について [記事を読む]

Leave a Comment

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。

^