WordPressのカスタム投稿タイプを企業サイトに使う場合の(超個人的)決定版

こんにちわ。
夢の中でコーディングした内容をコピペする方法がないか模索中の百田です。

エクストではWordPress3.0の頃から
カスタム投稿タイプを導入してサイトを構築しているのですが
3.0の頃と違い各所でも情報が豊富になりました。

今回は個人的メモを兼ねてカスタム投稿タイプの利用法をまとめたいと思います。

私がカスタム投稿タイプを利用する際のポイントはこちらです。

●プラグインは利用しない。
プラグインを利用する方法もありますが、シンプル好きなのでプラグインは使用せずにfunction.phpに記述します。
●企業サイトで使えるスラッグにする
スラッグに日本語が出てしまうなどはNG。企業サイトとして自然なURLを目指します。
●一覧用ファイルはひとまとめに
メンテナンス性を考え、taxonomy.phpは使用せずarchive.phpにまとめます。

今回は「書籍」という項目で
カスタム投稿タイプを利用する場合を想定して
構築を進めたいと思います。

最後にサンプルファイルを用意していますので
詳しくはサンプルファイルをダウンロードして確認してください。

1.カスタム投稿タイプの設定

function.phpに下記の内容を記述します。
基本的には「書籍」「book」の記述を
適宜置き換えるだけでOKです。

/* ★書籍ここらから★ */
register_post_type(
'book',
  array(
  'label' => '書籍',
  'hierarchical' => false,
  'public' => true,
  'query_var' => false,
  'menu_position' => 5,
  'has_archive' => true,
  'supports' => array('title','editor','author') 
  )
);

  /* カスタムタクソノミーを定義 */
  register_taxonomy(
	'book_cat',
	'book',
	array(
	'label' => 'カテゴリー',
	'hierarchical' => true,
	'rewrite' => array('slug' => 'book')
	)
  );
  /* カスタムタクソノミーを定義ここまで */
  
  /* 管理画面一覧にカテゴリを表示 */
  function manage_book_columns($columns) {
	$columns['book_category'] = "カテゴリー";
	return $columns;
  }
  function add_book_column($column_name, $post_id){
	if( $column_name == 'book_category' ) {
    //カテゴリー名取得
	if( 'book_category' == $column_name ) {
    	$book_category = get_the_term_list($post_id, 'book_cat', '', ', ', '' );
    }
    //該当カテゴリーがない場合「なし」を表示
    if ( isset($book_category) && $book_category ) {
        echo $book_category;
    } else {
        echo __('None');
    }
	}
  }
  add_filter('manage_edit-book_columns', 'manage_book_columns');
  add_action('manage_posts_custom_column',  'add_book_column', 10, 2);
  /* 管理画面一覧にカテゴリを表示ここまで */
  
/* ★書籍ここまで★ */

タクソノミー(カテゴリ)が不要な場合は、
15行目「 /* カスタムタクソノミーを定義 */」から
48行目「/* 管理画面一覧にカテゴリを表示ここまで */」までは不要です。

例としてタクソノミー(カテゴリ)に
「ノンフィクション(nonfiction)」を追加した場合
通常スラッグは以下のようになります。

●書籍一覧(カスタム投稿タイプ)

http://ドメイン/book/

●書籍一覧 > ノンフィクション一覧(タクソノミー)

http://ドメイン/cnonfiction/

ノンフィクション一覧のスラッグで
本来は親子関係をもった http://ドメイン/book/nonfiction/ としたいところですが
17行目で定義した _cat がくっついしまい親子関係がしっくりきません。

そこで22行目のようにリライトしてあげます。

'rewrite' => array('slug' => 'book') 

これでスラッグが親子をもった(ような)表示になります。

●書籍一覧 > ノンフィクション一覧(タクソノミー)

http://ドメイン/book/nonfiction/

function.php記述のポイントは、has_archive 、hierarchical、rewriteの設定ですが
これ以上突っ込まれると説明できる自信が無いので割愛します。。。
まぁこの通りに記述してやってください。

2.スラッグをページIDにするためのリライト設定

カスタム投稿タイプでは通常、/book/本の名前(記事タイトル)/ のように
スラッグ名に記事で設定したタイトルが入ってしまいます。
当然、日本語で本のタイトルを入れるとスラッグにも日本語が入ることになります。
ブログならまだよいのですが、企業サイトではあまり好ましくありません。
今回は /book/39.html のようにページIDで表示するようにします。
こちらもプラグインを利用する方法が多く出まわってますが
プラグインは使用せずにfunction.phpに記述します。

/* post_id.htmlにRewrite */
add_action('init', 'myposttype_rewrite');
function myposttype_rewrite() {
    global $wp_rewrite;

    $queryarg = 'post_type=book&p=';
    $wp_rewrite->add_rewrite_tag('%book_id%', '([^/]+)',$queryarg);
    $wp_rewrite->add_permastruct('book', '/book/%book_id%.html', false);

}

add_filter('post_type_link', 'myposttype_permalink', 1, 3);

function myposttype_permalink($post_link, $id = 0, $leavename) {
    global $wp_rewrite;
    $post = &get_post($id);
    if ( is_wp_error( $post ) )
        return $post;
    $newlink = $wp_rewrite->get_extra_permastruct($post->post_type);
    $newlink = str_replace('%'.$post->post_type.'_id%', $post->ID, $newlink);
    $newlink = home_url(user_trailingslashit($newlink));
    return $newlink;
}
/* post_id.htmlにRewrite */

こちらも「book」の記述を適宜置き換えてください。

3.パーマリンク設定の変更

管理画面の「パーマリンク設定」の「カスタム構造」で下記の内容に変更します。
※以前は「/%post_type%/%post_id%.html」でしたが「投稿」で不具合があるので変更しています。(追記2012/11/14)

/%category%/%post_id%.html

最後に「変更を保存」を押して保存してください。

4.詳細ページの設定

詳細ページは single.php を用意します。
これは、今までの構築方法と変わらないので割愛します。
single-book.php の専用ファイルを用意することで、
書籍専用の詳細ページを表示することもできます。

5.一覧ページの設定

一覧ページは archive.php を用意します。
詳細ページ同様、 archive-book.php を用意することで
専用の一覧ページを表示することもできますが、
今回は条件分岐で一覧を表示します。

<!-- 書籍一覧 -->
<?php if (( get_post_type() == 'book')) : ?>
  <h2>書籍</h2>
  <hr>
  <h3>カテゴリリスト</h3>  
  <ul>
  <?php wp_list_categories('title_li=&taxonomy=book_cat'); ?>
  </ul>
  <hr>
  <h3>書籍一覧 <?php single_term_title(); ?></h3>
  <ul>
  <?php if (have_posts()) : ?>
  <?php while (have_posts()) : the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
  <?php endwhile; ?>
  <?php endif; ?>
  </ul>
<?php endif; ?>
<!-- 書籍一覧ここまで -->

カスタム投稿タイプの一覧の archive.php と
タクソノミー(カテゴリ分類)一覧の taxonomy.php は通常、別ファイルになりますが
同じデザインの場合、2種類に分かれるとメンテナンス性が悪いので
archive.php のみを使い一つのファイルに集約します。

6.補足

これでカスタム投稿タイプの設定は完了です。
あとは、カテゴリや記事を登録して動作チェックしてみてください。
また、function.phpを変更する場合は、
最後に必ず管理画面のパーマリンク設定で
「変更を保存」をクリックして「カラ更新」をかけてください。
Rewrite設定が反映されずに404になることがあります。

今回の記事を書くにあたって、
下記ページを参考にさせて頂きました。感謝!

http://webpaprika.com/387.html
http://webpaprika.com/371.html
http://varl.jp/note/wp-3-1-custom-post-type-settings-summary

7.サンプルファイル

今回の内容をまとめた、超シンプルなサンプルテーマを用意しました。
サンプル内では「書籍」と「DVD」の
2種類の投稿タイプを設定していますので、より実践的な内容になっています。
DIMG0289 (2).gifご自由にどうぞ。
 
 
サンプルテーマをダウンロード
 
※「管理画面一覧にカテゴリを表示」にバグがあったためサンプルテーマを更新しました。2012/06/20            

19 注釈 “WordPressのカスタム投稿タイプを企業サイトに使う場合の(超個人的)決定版

  1. こんにちは。
    サンプルまで用意されており、説明がとても解りやすいですね!

    私の不勉強で恐縮ですが、一つ質問があります。

    現在静的なTOPページの下層に「WP」フォルダを作り、サンプルをUPして説明の通り行った(つもり)のですが、どういう訳か、CSSが切れた状態の静的なTOPページが表示される状態でした。
    ブラウザで表示されているURLをふと見ると、スラッグの文字の部分が薄くなっていました。

    もしや、下層にインストールされたWPの場合は特別必要な修正はありますでしょうか?
    もしよろしければ助言頂けるとありがたいです。

    宜しくお願いします。

  2. すみません。上記の「TOPページが表示される状態」だったのは、(ドメイン/book/) 等のスラッグのページの事です。説明がおかしかったらゴメンナサイ。。

  3. shioさんこんにちわ。

    記事内では触れていませんが、
    ドメイン/wordpress/ にWordPressを設置し、
    さらにドメインでアクセスした場合、
    WordPressのトップが表示される場合を想定してます。

    ですので下層にインストールして問題はありません。

    トップページが静的htmlなケースは
    経験したことが無いので、状況が把握できずに申し訳ないですが
    静的ページを削除した場合はうまく動作しますか?

    また、管理画面 → 一般設定で
    下記の設定はどうなっていますか?

    ・WordPress アドレス (URL)
    ・サイトアドレス (URL)

  4. 静的ページを削除した場合は、サーバーエラーが返されて表示が出来なくなりました。

    また以下については、
    ・WordPress アドレス  ドメイン/wp
    ・サイトアドレス  ドメイン/
    が設定です。

    よろしくお願いします。

  5. 管理画面のパーマリンク設定で「更新ボタン」を押して
    カラ更新しても症状は変わらないでしょうか?

    メール等でURLなどの状況をお教えいただければ
    もう少し詳しくアドバイスできると思いますので
    どうしても難しい場合はお気軽にご相談ください。

  6. こんにちは。
    こちらのソースを参考にさせていただいております。
    助かっております!

    一つ確認させてください。
    カスタム投稿の中でページ分割を行っています。
    その際に2ページ以降のページへ遷移した際に404 not found となります。

    通常は表示される↓
    http://domain.com/book/111.html
    最後にページ番号を付けると表示されない↓
    http://domain.com/book/111.html/2

    これは何か他に設定が必要となりますか?
    よろしければアドバイスをお願いいたします。

  7. さんどさんこんにちは。

    ページ分割は実案件で構築したことがないので
    想定してなかったのですが
    Rewriteの設定でつまづいてるみたいです。

    具体的な書き方を模索したのですが、
    なかなかうまくいかず
    リライト部分をプラグインで解決することでうまくいきました。
    記事のテーマとずれてしまうのですが
    プラグイン解決でOKでしたら下記の方法をお試しください。

    1.function.phpの107行目~133行目あたりの
     /* post_id.htmlにRewrite */を削除しアップし直す。

    2.Custom Post Type Permalinks(プラグイン)をダウンロードし有効化
     http://wordpress.org/extend/plugins/custom-post-type-permalinks/

    3.管理画面のパーマリンク設定の下の方に
     「カスタム投稿タイプのパーマリンク設定」が追加されているので、
     「/book」の横にあるテキストボックスに
     「/%post_id%.html」を追加し、変更を保存します。

    これで下記のようなurlでアクセスできるようになると思います。
     http://domain.com/book/111.html/2

  8. すごく参考になる記事ありがとうございます。当方で試したところ、サンプルでは
    カスタム投稿名/カスタムタクソノミー/ =book/nonfiction 等
    で一覧がされるのですが
    カスタム投稿名等を書き替えると
    カスタム投稿名ではOKですが、カスタムタクソノミーを加えると404エラーになります。
    いろいろ試した結果、「’rewrite’ => array(‘slug’ => ‘book’) 」
    をリライトさせず「’rewrite’ => true 」にすると
    カスタム投稿名/カスタムタクソノミー/
    で表示されました。これは何が原因と考えられますでしょうか?

  9. きよさんこんにちは。

    私の環境では「’rewrite’ => true」にすると、
    逆に404が出てしまいました。。

    「カスタム投稿名等を書き替えると」いうことですが
    例えば book を food 等に書き換えるということで間違いないしょうか?

    ちなみに、bookのままだとうまくいくでしょうか?

    bookのままでうまくいく場合は、
    文字列の置き換えがうまくいっていない可能性があります。

    あと確認点としては以下になります。

    ・管理画面のパーマリンク設定で更新できていない
    ・archive.php で条件分岐の書き換え忘れ→ < ?php if (( get_post_type() == 'book')) : ?>

    色々試していただいているとおもいますので
    上記に当てはまらない可能性もありますが。。

    もしお困りのようでしたらテーマファイルをお送りいただければ確認させて頂きます。

  10. 返答をいただいていたのにすみません。また、私の方で試してもう一度ご連絡します。

  11. こんにちは。

    素晴らしい記事をありがとうございます。

    紹介いただいたコードを参考に、カスタム投稿タイプ&分類をつくって、

    http://ドメイン/book/ターム名/

    のアーカイブを作れたのですが、

    functions.phpに書いたrewriteが影響しているのか、

    もともと固定ページとして存在していた

    bookというスラッグを持つ固定ページの子ページがnot foundになってしまいました。

    http://ドメイン/book/about.html

    というようなケースです。

    どうか、このrewrite処理したスラッグと、当初より存在する固定ページの同スラッグIDを親に持つ子ページのバッティングを防ぐ方法はないもんでしょうか。

    古い記事にコメントしてすみません。

  12. ココロさん

    かなりイレギュラーになってしまいますが
    archive.phpに固定ページの内容を呼び出すことで
    擬似的に表示可能だと思います。
    固定ページの拡張子がhtmlの場合の検証は行っていないので
    http://ドメイン/book/about/ で説明させていただきます。

    1.archive.phpの条件分岐から、aboutを除外します

    < ?php if (( get_post_type() == 'book')) : ?>

    < ?php if (( get_post_type() == 'book') && !is_tax('book_cat', 'about') ) : ?>

    2.archive.phpの下の方に下記の記述を追加します。
     これは、/about/のスラッグの場合、
     固定ページの内容を呼び出す記述になります。

    < ?php if(is_tax('book_cat', 'about')): /* about用 */ ?>
    < ?php $page_array = query_posts('pagename=about'); //ページのタイトルが「about」のものを抽出 $page = array_shift($page_array); //$page_arrayは多次元配列(二次元)の状態なので最初の配列を抽出 echo $page->post_content; //ここではpost_content(本文)を表示
    ?>
    < ?php endif; /* about用ここまで */ ?>

    以上でarchve.phpに固定ページを呼び出すことが出来ます。
    また、管理画面の固定ページは親子関係を持たずにaboutのみ登録してください。

    単純にpage.phpを使ってaboutのみ除外する方法があれば良いのですが、、、
    一度お試しください。

  13. はじめまして。素晴らしい記事を公開して下さってありがとうございます。
    お陰様でカスタム投稿設定も無事に出来上がりつつあります。
    随分前にお書きに成られた記事なのに、時間がたってからの質問ですみませんが、一つ教えて頂けないでしょうか。

    5のところで、archive-book.php を用意することで専用の一覧ページを表示することも可能と書かれていましたが、それをするにはどの部分をどのように変更すれば良いのか、教えて頂きたいなと思うのですが、もしこの投稿に気づいたらお知らせいただけると幸いです。ありがとうございました。

    1. あきらさん。初めまして。

      サンプルファイルのarchive.phpでは
      書籍一覧もDVD一覧も
      条件分岐しながら一つのarchive.php内にまとめられています。

      <!-- 書籍一覧 -->
      <?php if (( get_post_type() == 'book')) : ?>
       書籍一覧の内容
      <?php endif; ?>
      <!-- 書籍一覧ここまで -->
      
      <!-- DVD一覧 -->
      <?php if (( get_post_type() == 'dvd')) : ?>
       DVD一覧の内容
      <?php endif; ?>
      <!-- DVD一覧ここまで -->
      

      これを一つにまとめず
      書籍一覧、DVD一覧、それぞれにファイルを分離するということです。

      具体的にはarchive.phpのファイルをコピーして
      下記のファイル名にしたものを用意します。

      ・archive-book.php
      ・archive-dvd.php

      中身もarchive.phpのコピーで結構ですが
      下記の条件分岐は不要なので削除してください。

      <?php if (( get_post_type() == 'book')) : ?>
      <?php endif; ?>
      

      参考に archive-book.php (書籍一覧)の中身を記載します。
      見比べてもらうと条件分岐のない書籍一覧のためだけの
      記述になっていると思います。

      <?php get_header(); ?>
      
      
      <!-- 書籍一覧 -->
        <h2>書籍</h2>
        <hr>
        <h3>カテゴリリスト</h3>  
        <ul>
        <?php wp_list_categories('title_li=&taxonomy=book_cat'); ?>
        </ul>
        <hr>
        <h3>書籍一覧 <?php single_term_title(); ?></h3>
        <ul>
        <?php if (have_posts()) : ?>
        <?php while (have_posts()) : the_post(); ?>
          <li><a href="<?php the_permalink(); ? rel="nofollow">"><?php the_title(); ?></a></li>
        <?php endwhile; ?>
        <?php endif; ?>
        </ul>
      <!-- 書籍一覧ここまで -->
      
      <nav>
      <ul>
      <?php previous_posts_link('<li>前へ</li>') ?>
      <?php next_posts_link('<li>次へ</li>') ?>
      </ul>
      </nav>
      
      <?php get_footer(); ?>
      
  14. 数あるカスタム投稿関連ブログの中でこちらのサイトが一番わかりやすかったです。数日頭を悩ませ諦めかけていた問題が解決し、感謝の気持ちでいっぱいです。本当にありがとうございました!!

    1. ALICEさんこんにちは

      お役に立ててよかったです(^^)
      慣れるまで大変だと思いますが頑張ってください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です