更新日 2021.10.14

#6 Wordpressでサイトの下層ページを作る

下層ページの種類

TOPページは完成しました。続いては下層ページを作って見ましょう。
下層ページとはTOPページと頂点として、それ以降にリンクされているページのことです。

下層ページは2つの種類あります。 固定ページ 投稿ページ です。
固定ページ第2下層ページで、あまり変化のないLPや固定のページを作る際に使用します。
投稿ページカテゴリーページとリンクしており、RSSなどの配信に対応できるので投稿日などの時間を使うコンテンツページなどに使用します。
固定ページは、これまでまで作っていたような静的なhtmlページの作成、投稿ページはblogやニュース、商品一覧などのページを作るイメージで良いと思います。
コーポレート・ブランドサイトのようなものは固定ページを主に使い、blog・アフィリエイトなど記事を集めたページは投稿ページを主に使うことになります。

固定ページの作成

固定ページはpage.phpという名前のテンプレートファイルを自動で読み込みますのでpage.phpファイルを作成しましょう。

<?php
get_header();
?>

<div class="contents_wrap">
<main class="main" role="main">

  <?php if(have_posts()): while(have_posts()) : the_post(); ?>
    <h1><?php the_title();?></h1>
    <?php the_content(); ?>
  <?php endwhile; endif; ?>

</main>
</div>

<?php
get_footer();
新たにcontents_wrapmainラッパーを追加し、page.phpとして保存します。

▼解説
wordpressなどのCMSで、if文などのphpの構文をhtmlテンプレート内で書きたいときは、phpのコードを分割して記述する書き方があります。

if(have_posts()){        /* もし投稿があれば */
  while(have_posts()){   /* 全部の記事データをループ */
    the_post();          /* ひとつの記事を表示 */
  }
}
これは普通のphp構文



<body>
<main>
<?php if(have_posts()): while(have_posts()) : the_post(); ?> /*もしpostが存在すれば、あるだけ出力する*/
  

なにか文字情報〜

<?php endwhile; endif; ?> </main>
このようにifwhileを1行で書いて閉じタグまでの間に、htmlタグを入れることができます。
以下はwordpressでつくられている独自関数です。

have_posts()    /*記事があればtrueを返す*/
the_post()      /*特定の投稿のいろんな情報を取得*/
the_title()     /*タイトルを表示*/
the_content()   /*コンテンツ表示*/
get_sidebar()   /*サイドバーを表示*/
wordpressの独自関数はたくさんあるので、表示したい内容があれば、都度調べてみましょう。
wordpressの独自関数リファレンス

固定ページ用に新たなクラスを追加したので、下記のcssを、scss/style.scssに記述します。

/*wp下層ページ追加分*/
.contents_wrap{
  width:95%;
  margin:70px auto 0;
  @include mq('min','lg'){
    width:1024px;
  }
  .main{
    padding:10px;
    font:normal 1.2em/2 sans-serif;
    h1{
      margin-bottom:20px;
      color:#666;
      font:bold 2em/2 sans-serif;
    }
  }
}
wordpress管理画面の左側ナビから、固定ページをクリック。すでに入っている「プライバシーポリシー」ページで確認しましょう。

編集をクリックする

右上の歯車をクリックすると、メニューが出ます。
固定ページの属性という部分でpage.phpの上部にTemplate Name: 〜 で記述したテンプレート名が選べるようになっています。
固定ページという名前をつけたので、固定ページを選択します。
このように下層ページでは、テンプレートを作成し、コンテンツ内容を管理画面内で登録していきます。

投稿ページの作成

投稿ページのテンプレートはsingle.phpという名前になります。

<?php
get_header();
?>

<div class="contents_wrap">
<main class="main" role="main">

  <?php if(have_posts()): while(have_posts()) : the_post(); ?>
    <h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d'); ?></time>
    <span class="category"><?php the_category(', '); ?></span>
    <div class="content"><?php the_content(); ?></div>
  <?php endwhile; endif; ?>
</main>
</div>

<?php
get_footer();
single.phpとして保存します。


the_permalink()     /*パーマリンクを表示*/
the_time('Y-m-d')   /*日時を表示*/
the_category(', ')  /*投稿のカテゴリーをコンマ区切りで表示*/
これらはwordpressでつくられている独自関数です。

投稿ページ用に新たなクラスを追加したので、scss/style.scssに追記しましょう。

  /* page.php作成時に追記したmainを編集 */
.main{
  padding:10px;
  font:normal 1.2em/2 sans-serif;
  @include mq('min','lg'){
    margin-right:50px;
  }
  /* 以下を追加 */
  time{
    font:normal 1.1em/2 serif;
  }
  .category{
    display:inline-block;
    padding:0px 20px;
    border: 1px solid #ccc;
  }
  .content{
    margin:20px 0;
  }
  
  h1{
    margin-bottom:20px;
    color:#666;
    font:bold 2em/2 sans-serif;
    /* 以下を追加 */
    a{
      color:#666;
      @include mq('max','lg'){
        font-size:0.7em;
      }
    }
  }
}
投稿ページのサンプルページを表示させてみましょう。

テンプレート読み込み順

TOPページ、固定ページ、投稿ページ、一覧(アーカイブ)ページ、その他ページのテンプレートはWordPressが読み込む順位が決まっており、優先順位の高いテンプレートを探し、 最初に存在したテンプレートで表示させます。
優先順位TOPページ固定ページ投稿ページその他ページ
front-page.phppage-スラッグ名.phpsingle-ポストタイプ名.phpcategory.php
search.php
archive.php
author.phpなど
home.phppage-ID.php
page.phpsingle.php
index.php
テンプレートは、優先順位の①から読み込まれていき、①のファイルがない場合は②に進みそれでも無ければ...と進み、最後は④で表示されます。
※逆に固定も投稿も同じテンプレートで良ければ、index.phpのみ用意すればよいでしょう。

フロントページのテンプレートを変更する

index.phpをフロントページとして利用していましたが、front-page.phpに変更します。
index.phpコピーせずにfront-page.php名称変更リネームしましょう。
ただ、最も優先順位が低いテンプレートとしてindex.phpも欲しいので、 先程作成したsingle.phpをコピーして、index.phpとリネームしておきます。

ここまでのファイル構成

#7 固定ページにNEWS投稿を読み込む

トップページ(固定ページ)に、あるカテゴリとして登録した投稿記事の最新記事を4つだけ表示する

手順としてはこのような感じです。
  1. 管理画面 > 投稿 から4つの記事を新規追加・公開
  2. 表示するための設定をfunctions.phpに記述
  3. 特定カテゴリだけを表示させるテンプレートの作成
  4. TOPページのfront-page.phpにテンプレートのショートコードを記述

管理画面 > 投稿から新規で4つの記事を登録公開

左ナビから投稿 > 新規追加をクリック。タイトルをInstagram01にし、画像を選択しアップロードします。 右ナビのカテゴリを開いて新規カテゴリを追加からInstagramを追加します。この方法で4つの記事を作成します。画像は適当に選びましょう。
画像をダウンロード
図解
新規カテゴリーを追加し、記事に画像をアップロードします。

テキストに適当な文字を入れて、公開ボタンを押します。
例)インスタグラムにアップした写真の説明文なんかが入ってくるでしょう。

投稿一覧で見るとこの様になっています。

functions.phpで表示設定


<?php
/**
 * restaurant
 */

/* ① */
function first_image() {
  global $post;
  $first_img = '';

  preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
  $first_img = $matches[1][0];

  if(empty($first_img)){
    $first_img = "/assets/img/default.jpg";
  }
  return $first_img;
}


/* ② */
function instagram_template_part() {
  get_template_part('instagram');
}
add_shortcode('top_instagram', 'instagram_template_part');
①は、後ほど記述するモジュールテンプレートのinstagram.phpで使用する独自関数です。
②は、後ほど記述する固定ページfront-page.phpで使うショートコードを設定する関数です。
▼解説
① 後ほどテンプレートファイルで使用するための独自関数を設定しています。

function first_image() { }
instagramカテゴリーの各投稿記事において、ページの最初に表示される画像のパスを取得するための関数です


global $post;     /* $postはグローバル変数に指定しておきます。 */
$first_img = '';  /* 変数の初期化 */


preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
$post->post_contentで記事内容を取得できます。
正規表現によるマッチング
preg_match_all(パターン, 検索対象の文字列, 結果を入れる多次元配列変数)
$matches[1][0]で一番最初に出てくる画像のファイルパスを取得されているので、$first_imgに代入しています。

if(empty($first_img)){
  $first_img = "/assets/img/images/default.jpg"; /* ←画像は時間があるときに設定してみましょう*/
}
記事内で画像がなかったときのためのデフォルト画像を指定

② TOPページにinstagramカテゴリの画像を表示する

function instagram_template_part() {
  get_template_part('instagram');
}
instagram.phpのファイル名(拡張子の前)を指定して、読み込ませてます。


add_shortcode('top_instagram', 'instagram_template_part');
add_shortcode( ショートコードタグ, 実行する関数{コールバック関数} );
ページ内にtop_instagramというショートコードがあれば、 独自関数のinstagram_template_part()関数を実行する。

Instagramカテゴリの記事だけを表示させるモジュールテンプレート作成

ページ表示用テンプレートと同じ考え方ですが、今回はページとしての利用ではなく、TOPページfront-page.phpへ埋め込むための、 モジュールテンプレートとして作成します。

<?php
/**
 * instagram表示モジュール
 */

$args = [
  'numberposts' => 4,
  'category'    => 3
];
$posts_array = get_posts($args);
global $post;
?>

<ul class="instagram__list">
  <?php if($posts_array): foreach( $posts_array as $post ): setup_postdata($post); ?>
    <li>
      <a href="<?php echo the_permalink(); ?>">
        <div class="instagram__list-img">
          <img src="<?php echo first_image(); ?>" alt="<?php the_title(); ?>">
          <?php the_excerpt(); ?>
        </div>
      </a>
    </li>
  <?php endforeach; wp_reset_postdata(); endif; ?> 
</ul>
instagram.phpという名前で保存します。
▼解説

$args = [
  'numberposts' => 4, /* 取得する記事数 */
  'category'    => 3  /* カテゴリID */
];
$posts_array = get_posts($args);
global $post;
get_posts()のオプションを$argsで設定します。 get_posts()はオプションの内容に沿った記事一覧を取得します。
$posts_arrayに全データが入ります。
後ほど使う$postをglobal設定しておきます。


<?php if($posts): foreach($posts as $post): setup_postdata($post); ?>
ちょっとわかりにくいですが、以下のものを1行で書いてあります。

if($posts){
  foreach($posts as $post){
    setup_postdata($post);
    処理・・・
  }
}
$postsデータが存在すれば、foreachで配列全てをループさせる処理です。
setup_postdata($post)はグローバル変数$postを使うための設定です。なくても使えることもあるが便宜上入れます。
setup_postdata($post)の引数は必ず$postにします。 ですので、foreachのの名称は必ず$postにするのがルールです。
また上記に記したとおり、$postは事前にグローバル変数設定しておきましょう。

<img src="<?php echo first_image(); ?>" alt="<?php the_title(); ?>">
first_image(); はfunctions.phpで設定した、最初の画像を取得する独自関数

get_posts関数で指定している「カテゴリーID」は3になっていますが、カテゴリを一度削除し作り直したりすると番号が新しく発行されます。
アドレスの赤い部分からカテゴリーIDを見つけて設定します。

front-page.phpにショートコードを記述

front-page.php内に以下の内容がありますが、

<ul class="instagram__list">
  <li>
    <a href="<?php echo get_permalink(0); ?>">
      <div class="instagram__list-img">
        <img alt="" src="<?php echo get_template_directory_uri(); ?>/assets/img/news01.jpg">
      </div>
    </a>
  </li>
  ・
  ・
  ・
</ul>

<?php echo do_shortcode('[top_instagram]'); ?>
上記ulタグを、先ほど作成したinstagram.php(instagramカテゴリの表示パーツ)に差し替えるために、 functions.phpで設定したadd_shortcode()で設定したショートコード'top_instagram'を、 wordpress独自関数のdo_shortcode()で表示できます。

<section class="instagram">
  <h2 class="instagram__title">INSTAGRAM</h2>
    <?php echo do_shortcode('[top_instagram]'); ?>
  <div class="instagram__button">
    <a href="#">FOLLOW US</a>
  </div>
</section>
sectionは上記の記述になります。

&__list {
  ・
  ・
  ・
  &-img p{  /* 追加しておきましょう */
    padding-top:5px;
    font:normal 0.7em/1.3em sans-serif;
  }
}
instagram.phpで設定したthe_excerpt();で、テキストがpタグにラップされて出力されますので、style.scssに上記のものを設定。
見た目は同じですが、写真はモジュールテンプレートで表示されています。
試しに4枚目の投稿をして挙動を確認してみましょう。

また、ショートコード [top_instagram] が直接画面に表示されている場合は以下のとこを確認してみましょう
  1. 各関数名を打ち間違えていないか
  2. functions.phpファイル名がfunction.phpと、最後のsがない

ファイル構成をまとめてみました

モジュール化した場合は手間がかかっているように思えますが、管理画面から投稿した記事をレイアウトに使えるために、 htmlの知識がなくてもwebサイトを更新できるメリットがあります。

固定記事をモジュール用途で利用する

また、とある固定ページで作った一つの記事をモジュールとして使うことも可能です。

<div>
<?php $page_info = get_page_by_path('スラッグ名');
      $page = get_post($page_info); ?>  /* スラッグ名の記事を取得します */
    <h1><?= $page->post_title; ?></h1>  /* $page->post_title などで情報を表示させます */
    <?= $page->post_content; ?>
</div>
固定ページの最後に毎回入れる情報があった場合、全ページに入れるのはめんどくさいので、固定ページの記事を一つ作り、その記事を読み込ませます。誰でも編集できるようになるので便利ですね。
対応させたいテンプレートファイルの該当箇所に、上記のコードを入れてあげればOKです。

ここまでのファイル構成
コピーしました
RSS https://cbc-study.com/rss.xml 
質問などあればSlackで! 誰でも無料でできます
cbc-study.slack.com