WordPressの勉強4（自分用）

参考：『基礎からのWordPress』高橋のり

#カスタム投稿タイプで中規模サイトの作成

#カスタム投稿タイプで更新型コンテンツ
##カスタム投稿タイプとは
・ブログとは別の更新型コンテンツ
・企業のサイトなどでは、ニュース・お知らせなどブログとは別にこのようなコンテンツのニーズが高い

###WordPressの投稿タイプ
・ブログや固定ページにはデフォルトの投稿タイプがある
→ブログの投稿：投稿タイプ「post」
→固定ページの投稿：投稿タイプ「page」
・一方、カスタム投稿タイプというのは、自分で任意の名前をつけた投稿タイプのこと
→管理画面に独自の投稿を増やすことができる
→お知らせの投稿：投稿タイプ「information」（カスタム投稿タイプ）

##カスタム投稿タイプを利用する準備
・カスタム投稿タイプは自分で作成しなければ利用できない
→functions.phpにいろいろなコード記述
→今回はプラグイン（Custom Post Type UI)

###プラグインのインストール
・プラグイン→新規追加
・CPT UI→新規追加
・設定
→投稿タイプ名に「Information」（PHPでも利用するので半角英数字）
→ラベルに「お知らせ」（メニューに表示される名前）
→Advanced Optionsを押す
→Has ArchiveをTrueで作成（投稿を一覧表示で表示するため）
・階層→親子をつくることもできる
・ビルトイン分類→ブログと同じカテゴリーやタグを利用することもできる

##カスタム投稿タイプを使ってみる
・CPTでカスタム投稿タイプを作成すると、管理画面のメニューには新しく「お知らせ」というメニューが追加される
・Addお知らせで追加
・/information/でアクセス（アーカイブ表示）
・このとき使用されるテンプレートファイル
1.archive-[post_type].php
2.archive.php
3.index.php
→post_type=informationにして作成

##トップページにお知らせを表示する
・サブループを作成する
・トップページを固定ページtop.phpで作成したので、top.phpに記述する

・top.php抜粋

```lang:top.php
<img src="<?php header_image(); ?>" height="<?php echo get_custom_header()->height; ?>" width="<?php echo get_custom_header()->width; ?>" alt="" />
省略
<aside id="ingromation">
  <h2>お知らせ</h2>
省略
<?php $args = array( 'post_type' => 'information', 'post_per_page' => 5); $information = new WP_Query( $args ); ?>
  <?php if ($information -> have_posts() ): ?>
    <ul>
    <?php while ($information -> have_posts()) : $information -> the_post(); ?>
      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?>&nbsp<span>-<?php echo get_the_date(); ?></span></a></li>
    <?php endwhile; ?>
    </ul>
  <?php endif; ?>
  <?php wp_reset_postdata(); ?>
省略
</aside>
```

・カスタムヘッダー画像、その下にお知らせの投稿を表示（レイアウトはCSSで行う）
・WP_Queryによるサブループに渡すパラメータ
→post_typeにはカスタム投稿名である「information」
→posts_per_pageには最大表示件数を指定
・ul要素とli要素でマークアップするのでul要素はwhile文の外に記述することに注意する
・ループが終わったらwp_reset_postdataでリセット完了

##お知らせの個別投稿を表示する方法を見ていく
・テンプレート階層
1.single-[post-type].php
2.single.php
3.index.php
→single-information.php

```lang:single-information.php
<?php get_header(); ?>
<div id="main">
<?php if(have_posts()) : ?>
  <?php while(have_posts()) : the_post(); ?>
    <h3><?php the_title(); ?></h3>
    <time class ="post-date" datetime="<?php echo get_the_date("Y-m-d"); ?>"><?php echo get_the_date(); ?></time>
    <?php the_content(); ?>
    <nav class="post-navi">
      <span id="prev"><?php previous_post_link('%link', '&laquo; %title'); ?></span>
      <span id="next"><?php next_post_link('%link', '%title &raquo;'); ?></span>
    </nav>
  <?php endwhile; ?>
<?php else: ?>
  <h3>お知らせが見つかりません</h3>
  <p>お探しのお知らせは見つかりませんでした</p>
<?php endif; ?>
</div><!-- main -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
```

・ループの中身はタイトル、日付、コンテンツの表示のみ
・post-navi：次のお知らせ、前のお知らせに移動するリンクを表示するコード

##カスタム投稿タイプ用のパンくずリスト
・パンくずリストを作成したカスタム投稿タイプ「Information」に対応させる
・まずお知らせを一覧表示させるアーカイブページのパンくずリストを作る
・「Has Archive」を「True」にしている状態では、is_post_type_archiveという条件分岐タグを利用する
→is_post_type_archive('information')とすれば、カスタム投稿タイプ「information」のアーカイブページが表示されている場合という条件分岐に使える
・コードの概要
`省略
<?php elseif (is_post_type_archive('information')) : ?>
<li>お知らせ一覧</li>
<?php elseif(is_category()) : ?>
カテゴリーの場合の記述`
→関数化してfunctions.phpに記述

・次にお知らせの個別記事が表示されている状態でのパンくずリスト
・is_singularという条件分岐タグを利用する
→is_singular('information')とすれば、カスタム投稿タイプ「information」の個別記事が表示されている場合という条件分岐になる
・コードの概要
`省略
<?php elseif (is_singular('information')) : ?>
<li><a href="<?php echo home_url('/'); ?>/information/">お知らせ一覧</a></li>
<li>&gt;</li>
<li><?php single_post_title(); ?></li>
<?php elseif(is_singular('post')) : ?>
ブログの個別記事の場合の記述`
・is_singleより後だとブログ記事と同じパンくずリストが適用されてしまうので、必ずis_singleより前に記述すること
→ブログの個別記事を明示的に条件分岐したい場合は、is_singular('post')というような条件分岐を利用したほうがよい

##カスタム投稿タイプ用のサイドバー
###タイトル部分
・お知らせの一覧ページのコード
`<?php elseif(is_post_type_archive('information')) : ?>
<h2>お知らせ</h2>
<h3>INFORMATION</3>`
→is_post_type_archivesを使えば簡単に条件分岐できる
・お知らせの個別記事
`<?php elseif(is_singular('information') ) : ?>
<h2>お知らせ</h2>
<h3>INFORMATION</h3>`
・内容が変わらないためまとめる
`<?php elseif(get_post_type() == 'information') : ?>
<h2>お知らせ</h2>
<h3>INFORMATION</h3>`

###アイキャッチ部分
・同じ写真を使うことにする
・sidebar.php（抜粋）
`<?php elseif(get_post_type() == 'information') : ?>
<img src="<?php echo get_template_directory_uri(); ?>/images/info.jpg" width="214" height="132" alt="">`
→アーカイブページでは管理画面でアイキャッチ画像を設定することができないため、事前にimagesフォルダ内に画像を用意しておく

###リンク部分
・一覧ページでは本文の方で一覧を表示しているので不要
・個別のお知らせページでは、他のお知らせに素早くアクセスできるように新着順で表示させる
・sidebar.php （抜粋）

```lang:sidebar.php
<?php if (is_singular('information') ): ?>
<nav class="sidebar-navi">
<?php $args = array('post_type' => 'information', 'posts_per_page' => 5); $information = new WP_Query($args); if($information -> have_posts() ): ?>
  <ul>
  <?php while ($information -> have_posts()) : $information -> the_posts(); ?>
  <li class="brother"><a href="<?php the_permalink() ?>"><?php the_title(); ?>&nbsp<span class="date">- <?php echo get_the_date(); ?></span></a></li>
  <?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
  <li><a href="<?php echo home_url('/'); ?>/information/">&raquo; お知らせ一覧</a></li>
  </ul>
</nav>

<?php elseif(is_search()) : ?>
検索結果の場合
```

・WP_Queryを使ったサブループ
→'post_type' => 'information' とすることで、カスタム投稿タイプinformationの記事をループで表示するように指定している

#カスタム投稿タイプとカスタム分類
・カスタム投稿を分類して表示させる方法により、製品一覧の各ページを作成していく

##カスタムタクソノミー（カスタム分類）とは
・ソファー：家具の種類という分類、ダイニング：お部屋タイプという分類

###カスタム分類の概要
・カスタム分類というのは、自分で作る「投稿の分類」のこと
・ブログにはもともと「カテゴリー」や「タグ」といった、記事を分類する方法が用意されている
→カスタム投稿「製品」の中のカスタム分類「家具の種類」
　→ターム：「ソファー」「テーブル」　それぞれ一覧表示することが可能
・カスタム分類は一つの投稿タイプに対して複数設定することも可能
→カスタム投稿「製品」の中にカスタム分類「ルームタイプ」を追加
　→タームも1つの記事に対して複数設定することが可能

##カスタム分類の作成手順
・新しい製品が出る度に追加されていくため、カスタム投稿を利用して作成する

###カスタム投稿タイプの作成
・CPTを使ってカスタム投稿タイプ「製品（product）」を作成する
→製品全てを一覧で表示する予定がないため、HasArchiveはFalseのままにしておく

###カスタム分類の作成
・CPTを使って作成することができる
→新規作成
→分類名：item
→ラベル：家具の種類
→製品をチェック
・階層を作成することもできる
・同じ要領でルームタイプも

###タームの作成
・製品→家具の種類→チェア
・これらのタームはURLの中で使われるので、スラッグは半角英数字にしておく

##記事の投稿と表示
・カスタム投稿「製品」で、いくつか記事を投稿してみる
→同時に2つのカスタム分類を利用してみる
→/roomtype/dining/（/カスタム分類名/タームのスラッグ）
　→カスタム分類で分類された一覧がindex.phpで表示される
・一覧ページのテンプレート階層
1.taxonomy-[taxonomy]-[term].php
2.taxonomy-[taxonomy].php
3.taxonomy.php
4.archive.php
5.index.php
・ブログでは日付など表示する必要があるが、「製品」の場合は必要なし
→taxonomy.phpを作成してレイアウトなども変更
・レイアウトや表示するものがちがう場合は、index.phpとは別に、taxonomy.phpやさらに細かく分けられるtaxonomy-[taxonomy].phpを用意する
・サブタイトルを個別ページと同じようにカスタムフィールド「subtitle」で作成

##製品の個別ページで関連製品を表示
・個別記事のテンプレート階層
1.single-[post-type].php
2.single.php
3.index.php
→single-product.phpを用意してブログの個別ページと区別

###関連商品を表示する
・ブログの記事の下に同じカテゴリーの関連記事を表示したのと同様に
・ここでの関連商品とは、同じタームが設定されている商品
→ブログとは違い、カスタム分類によって分類されているため、そのあたりのコードが異なる

```lang:single-product.php
<?php if(get_the_terms( $post->ID, 'roomtype' ) || get_the_terms( $post->ID, 'item')) :
  $args = array( 'post_type' => 'product',
    'post__not_in' => array($post->ID), 
    'orderby' => 'rand', 
    'posts_per_page' => 6, 
    'tax_query' => array('relation' => 'OR', 
    array( 'taxonomy' => 'roomtype',
           'field' => 'slug',
           'terms' => get_my_term_array("roomtype") ),
    array( 'taxonomy' => 'item',
           'field' => 'slug',
           'terms' => get_my_term_array("item") ) )
    );
  $related = new WP_Query($args);
  if( $related -> have_posts() ) : ?>
    <hgroup>
      <h2>関連製品</h2>
      <h3>Related products</h3>
    </hgroup>
  <?php while( $related->have_posts() ) : $related->the_post(); ?>
    <article>
      <hgroup>
        <h3><?php the_title(); ?></h3>
    <?php if( get_post_meta($post -> ID, 'sub-title', true)) : ?> 
        <h4 class="subtitle"><?php echo get_post_meta( $post -> ID, 'sub-title', true); ?></h4>
    <?php else: ?>
        <h4 class="subtitle">SUBTITLE</h4>
    <?php endif; ?>
      </hgroup>
    <?php if(has_post_thumbnail()) : the_post_thumbnail(); ?>
    <?php else: ?>
      <img src="<?php echo get_template_directory_uri(); ?>/images/default.jpg" alt="" />
    <?php endif; ?>
    <p class="link"><a href="<?php the_permalink() ?>"詳しく見る</a></p>
    </article>
  <?php endwhile; ?>
  <?php wp_reset_postdata(); ?>
  <?php endif; ?>
<?php endif; ?>
```

・タームが設定されているかどうかを確認する
→get_the_terms(id,taxonomy);：投稿記事のターム情報を配列で返す
　→id:記事のID, taxonomy:分類名
→roomtypeとitemにタームがつけられているかどうかという条件分岐を作成する
　→カスタム分類は必ずしもつけられているかるかわからないため
・カスタム投稿タイプ名を指定
・サブループから「現在表示中の投稿」を除く
・表示順をランダムにする
・表示最大件数を6件にする

・tax_query：カスタム分類についての指定を行う
→relation:投稿を取得する際の関連性をORまたはANDで指定。
　→OR:または　AND:かつ
・taxonomy:カスタム分類名を指定
・field:タームをIDで指定するか、スラッグで指定するかを記述
・terms:タームを配列で指定する
→ここではget_my_term_arrayというオリジナルの関数
　→現在表示されている投稿につけられたタームをカスタム分類を指定して取得
・get_my_term_array関数で取得した値はタームを格納した配列なので、実際には下記のような指定になっているのと同様
`'terms' => array('table', 'chair')`
・以降はWP_Queryを使ったサブループ

##固定ページで導入ページを作る
・それぞれに分類されたページ（ソファーの一覧ページなど）は、ブログでいうカテゴリーページと同じ位置づけ
・サンプルサイトでは固定ページを使って「製品一覧」を作っている

##カスタム分類のパンくずリスト
・カスタム分類による「一覧表示」（taxonomy.phpによるアーカイブ）と「個別製品表示」（single-product.phpによる個別投稿表示）ページ用の2種類を作成

###一覧表示ページのパンくずリスト
`<?php elseif (is_tax()) : ?>
<li><a href="<?php echo home_url('/'); ?>/products/">製品一覧</a></li>
<li>&gt;</li>
<li><?php single_cat_title(); ?></li>`
・カスタム分類（タクソノミー）のアーカイブ表示の場合は、条件分岐タグis_taxを利用する
→「製品一覧」のページは固定ページで作っているので、そのままリンクをはっている
→タクソノミーのタイトルはカスタム分類でもカテゴリー名を表示するsingle_cat_titleで
・functions.php内で関数に
`elseif (is_tax()) {
$str .='<li><a href="' . home_url('/) . '/products/">製品一覧</a></li>'."/n";
$str .='<li>&gt;</li>'."/n";
$str .='<li>' . single_cat_title( '' , false ) . '<li>'."/n"; }`

###製品個別ページのパンくずリスト
`<?php elseif (is_singular('product')) : ?>
<li><a href = "<?php echo home_url('/'); ?>/products/">製品一覧</a></li>
<li>&gt;</li>
<?php $terms = get_the_terms( $post->Id, 'roomtype' );
if ( $terms ) : $term = array_shift ( $terms ); ?>
<li><a href = "<?php echo get_term_link( $term, 'roomtype' ); ?>"><?php echo $term -> name; ?></a></li>
<li>&gt;</li>
<?php endif; ?>
<li><?php single_post_title(); ?></li>
<?php elseif (is_singular('post')) : ?>
ブログの個別記事の場合…`

・カスタム投稿であるproductの個別ページは、is_singular('product')で条件分岐する
・get_the_termsで投稿につけられたタームを取得する
・タームは必ずつけられているとは限らないので、「タームがある場合」という条件分岐をする
・タームは1つとは限らないので、PHPの関数array_shiftを使って、配列の一番はじめのものだけを取得する
・get_term_link(term, taxsonomy)：タームのリンクを取得する
→term:タームのオブジェクトまたはID, taxsonomy:分類名
・$term -> nameでタームの名前を取得してechoで出力して完成
・functions.phpで関数にする
`elseif (is_singular('product')) {
$str .='<li><a href="' . home_url('/') .'/product/">製品一覧</a></li>'."/n";
$str .='<li>&gt;</li>' . "/n";
$terms = get_the_terms( $post->ID, 'roomtype' );
if ($terms) {
$term = array_shift($terms);
$str .='<li><a href="' . get_term_link( $term, 'roomtype' ) . '">' . $term -> name .'</a></li>' . "/n";
$str .='<li>$gt;</li>' . "/n"; }
$str .='<li>'. single_post_title( '', false ) . '</li>' . "/n"; }`

##カスタム分類のサイドバー
###見出し
・サンプルサイトでは、固定ページで作成した製品一覧ページ、カスタム分類一覧ページ、個別製品ページでも同じサイドバーを表示する
・見出しも全て同じで構わないので条件分岐して直接HTMLで記述する
・sidebar.php抜粋
`<?php elseif (is_tax() || is_singular('product')) : ?>
<h2>製品一覧</h2>
<h3>PRODUCTS</h3>
<?php else: ?>`
・固定ページである製品一覧ページは固定ページ用のコードがそのまま利用できるので、ここではカスタム分類一覧ページと、個別製品ページ用の条件分岐を記述すればOK
・条件分岐タグis_taxでタクソノミー（カスタム分類）一覧ページ、is_singular('product')でカスタム投稿「product」の個別製品ページという条件分岐になる

###アイキャッチ画像
・製品のアーカイブページは管理画面で編集することができない＝アイキャッチ画像を設定できない
・imagesフォルダにあらかじめ画像を用意しておく
・sidebar.php抜粋
`<?php elseif(is_tax()) : ?>
<img src="<?php echo get_template_directory_uri(); ?>/images/<?php echo get_term_slug(); ?>.jpg" alt="">
<?php else: ?>`
・get_term_slugは、このテーマのオリジナル関数で現在表示されているタームのスラッグを取得する関数
→画像ファイルをスラッグにしておく

・個別ページでもアーカイブページと同じように、投稿につけられたタームのスラッグを取得して画像のファイル名に利用
・sidebar.php抜粋
`<?php elseif(is_singular('product')) :
$terms = get_the_terms( $post->ID, 'roomtype' );
if( $terms ) : $term = array_shift($terms) ;>
<img src="<?php echo get_template_directory_uri(); ?>/images/<?php echo $term -> slug; ?>.jpg" alt="">
<?php else: ?>
<img src="<?php echo get_template_directory_uri(); ?>/images/no-image-sidebar.jpg" width="214" height="132" alt="">
<?php endif; ?>
<?php elseif(is_tax()): ?>`
・カスタム分類「ルームタイプ」につけられたタームを取得する
・＄term -> slugとして、タームのスラッグを取得

###リンク部分
・アコーディオンメニューの仕組み…jQuery
・サイドバーの仕上げとして最後にタームをリストで表示し、ローカルメニューを完成する

```lang:sidebar.php
<?php elseif (is_page('products') || is_tax() || is_singular('product')): ?>
  <nav class ="structure">
    <ul class="accordion">
    <?php $roomtype_args = array (
      'title_li' => '<span class="header">ルームタイプから探す</span>',
      'orderby' => 'id',
      'taxonomy' => 'roomtype' );
    wp_list_categories($roomtype_args);
    $item_args = array(
      'title_li' => '<span class="header">家具のタイプから探す</span>',
      'orderby' => 'id',
      'taxonomy' => 'item' );
    wp_list_categories($item_args); ?>
    </ul>
  </nav>
```

・まず条件分岐で大枠を作る
→固定ページ「製品一覧」、カスタム分類のアーカイブページ、製品の個別ページの3種類のページ全て同じようにリストを表示するため、||（OR)でつないでいる
・最終的にはテンプレートタグwp_list_categoriesを利用してタームをリスト表示するが、リストは2種類あることに注意
・＄roomtype_argsと＄item_argsの部分でwp_list_categoriesに渡すパラメータを設定する
→title_liにはHTMLタグも指定できる
→orderbyでは表示順をid順にし、taxonomyでカスタム分類名を指定する
・アーカイブページでは、アクティブになっているリストにはcurrent-catというクラスもつくので、CSSでスタイルを変更できる

###タームの説明文
・カテゴリーやタグ、タームには編集画面に説明文を入力する項目が設けられている
→ここに記述した説明をサイトに表示させることも可能
`<?php if(item_description()) : ?>
<p><?php echo term_description(); ?></p>
<?php endif; ?>`
→管理画面がない＝カスタムフィールドが設定できないページでは、サブタイトルなどに使える