WordPress カスタム投稿タイプの使い方とその力

目次

1. カスタム投稿タイプとは?

WordPressには、更新コンテンツを一覧管理できる項目として、「投稿」と「固定ページ」の2つが用意されています。
ただのブログならば十分ですが、WordPressをCSMとしてWebサイトを構築しようと思うと不十分です。
なぜなら、一般的なWebサイトには、ブログの他に、ニュースやフォトギャラリー、FAQなど、様々は更新コンテンツが考えられ、投稿タイプも様々だからです。
初期状態でも、カテゴリーで投稿タイプを分けて管理することはできますが、やはり投稿タイプが異なる記事はそれぞれ一覧管理できた方が便利です。

それを実現するのが、「カスタム投稿タイプ」という機能です。
WordPress 3.0 から導入された「カスタム投稿タイプ」を使えば、自由に投稿タイプを追加できるようになります。
例えば、「更新履歴」という投稿タイプを追加すると、管理画面のサイドメニューに「更新履歴」専用の投稿メニューが設置されます。

投稿タイプ – WordPress Codex

2. カスタム投稿タイプの導入(プラグインを使う方法)

プラグイン: Custom Post Type UI

このプラグインを使うと、簡単にカスタム投稿タイプを追加することが出来ます。
※後に説明する 3. 直接コードを書く方法 の方がおすすめです。

インストールして有効化

プラグイン: Custom Post Type UI をインストールして有効化すると、管理画面のサイドメニューに「Custom Post Types」というメニューが追加されます。

使い方

管理画面 > Custom Post Types > Add New

今回は、左側半分だけを使います。右側の「カスタム分類作成」は使いません。

投稿タイプ: カスタム投稿タイプの名前。日本語はダメです。(ex. news)
ラベル: カスタム投稿タイプのラベル。管理画面のサイドメニューのところに表示されるラベルです。(ex. 更新履歴)
単数形のラベル: カスタム投稿タイプの名前の単数形。日本語では単数形と複数形を区別することはないので関係ありません。
説明: なにか書いておきたければどうぞ。

必要事項を記入して「Create Custom Post Type」ボタンを押せば、カスタム投稿タイプが追加されます。

オプション設定

「Advanced Label Options · Advanced Options」から、オプション設定をすることができます。

特筆すべきは、以下の2項目です。

メニューの位置: 管理画面のサイドメニューでの表示位置を決める変数です。

5: 「投稿」の下
10: 「メディア」の下
20: 「ページ」の下
null: 一番下

一般的には「5」になるかと思います。

サポート: 投稿画面に表示する項目を限定することができます。

不要な項目のチェックは外しておくといいでしょう。

3. カスタム投稿タイプの導入(直接コードを書く)

テーマディレクトリの functions.php に、以下のコードを記述することで、カスタム投稿タイプを導入することができます。

add_action('init', 'my_custom_post_type');

function my_custom_post_type() {
	$labels = array(
		'name' => _x('更新履歴', 'post type general name'),
		'singular_name' => _x('更新履歴', 'post type singular name'),
		'add_new' => _x('新しい更新履歴を追加', 'book'),
		'add_new_item' => __('新しい更新履歴を追加'),
		'edit_item' => __('更新履歴を編集'),
		'new_item' => __('新しい更新履歴'),
		'view_item' => __('更新履歴を編集'),
		'search_items' => __('更新履歴を探す'),
		'not_found' => __('更新履歴はありません'),
		'not_found_in_trash' => __('ゴミ箱に更新履歴はありません'), 
		'parent_item_colon' => ''
	);
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => true,
		'show_ui' => true, 
		'query_var' => true,
		'rewrite' => true,
		'capability_type' => 'post',
		'hierarchical' => false,
		'menu_position' => 5,
		'supports' => array('title','editor')
	); 
	register_post_type('news',$args);
}

変数等については、こちらを参考にしてみてください→ register_post_type

4. カスタム投稿タイプを表示する

通常のループ処理に、「特定のカスタム投稿タイプ」という条件を追加します。
最後に生成したループをリセットするのを忘れないようにしましょう。

<?php if (have_posts()) : query_posts('post_type=news'); ?>
	<?php while (have_posts()) : the_post(); ?>
	<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
	<div class="entry"><?php the_content(); ?></div>
	<?php endwhile;>
<?php else : ?>
	Not Found.
<?php endif; ?>
<?php wp_reset_query(); ?>

※ちなみに

WordPressでループを生成する関数には、get postsquery_posts()WP_query() などがあります。

それぞれの違いについては、こちらの記事で解説しています→WordPressのループの仕組みを深く知る query_posts() と get_posts() の違い

以上、「カスタム投稿タイプ」を使うことで、ブログや固定ページだけではなく、ニュースやフォトギャラリー、FAQなど、様々は投稿タイプを別々に管理、投稿できたり、最適な方法で自由に表示させることが出来るようになります。

5. カスタム投稿タイプとカスタムフィールドを組み合わせる

このカスタム投稿タイプと、前回解説したカスタムフィールドを組み合わせると、いよいよWordPressをCMSとしてWebサイトを構築できそうな気配がしてきます。

サンプルとして、トップページの記事一覧の上に、更新履歴を5件表示させるようにしてみましょう。

まず、「news」という投稿タイプ専用のカスタムフィールドテンプレートを作成します。

「カスタムポストタイプ (カンマ区切り):」の欄に「news」と入力します。
こうすることによって、このカスタムフィールドテンプレートは、「news(更新履歴)」の投稿欄でのみ使用可能になります。

テンプレートの設定は以下のようにします。

[date]
type = text
size = 35
date = true
dateFormat = yyyy/mm/dd
label = 日付

[message]
type = textarea
rows = 4
cols = 40
htmlEditor = true
label = 内容

更新履歴の投稿画面はこうなりました。

※カスタムフィールドテンプレートの項目のみで、「タイトル」「本文」の入力が必要ない場合、カスタム投稿タイプを生成するコードの supports の値を以下のように設定します。

'supports' => array(null)

index.php に、以下のコードを追加して、更新履歴を表示してみましょう。

<?php if (have_posts()) : query_posts('post_type=news'); ?>
	<?php while (have_posts()) : the_post(); ?>
	<h2><a href="<?php the_permalink() ?>"><?php echo get_post_meta($post->ID, 'date', true); ?></a></h2>
	<div class="entry"><?php echo get_post_meta($post->ID, 'message', true); ?></div>
	<?php endwhile; ?>
<?php else : ?>
	Not Found.
<?php endif; ?>
<?php wp_reset_query(); ?>

いかがでしょうか?

WordPressは、もはやただのブログツールではないのです。
カスタム投稿タイプとカスタムフィールドを組み合わて応用すれば、CMSとして本格的なWebサイトの構築も可能なのです。

  • soda

    カスタムフィールドの勉強をしている最中にこのサイトを知り、
    大変ありがたいと思いつつ、意気揚々とトライしてみました。

    まずはじめに、

    >>3. カスタム投稿タイプの導入(直接コードを書く)

    という文章の下に表示されているコードをコピーし、
    デフォルトテーマ:Twenty Elevenの「functions.php」に追記することで
    サイドメニューに「更新履歴」を表示させることができました。

    次に、Custom Field Templateプラグインのインストールと、その後に
    「カスタムポストタイプ (カンマ区切り):」に”news”と設定し、
    「テンプレートコンテンツ」も本サイトの指南通りに設定しました。

    最後に、Twenty Eleven直下の「index.php」内のコードを指南通りに書き換えましたが、

    管理画面 > 更新履歴 > 新しい更新履歴を追加 を押下しても、
    更新履歴の投稿画面がデフォルトの「投稿」と変わらない状態となっています。

    ※ちなみに、Twenty Eleven直下の「index.php」内のコードは

    >> index.php に、以下のコードを追加して、更新履歴を表示してみましょう。

    という文章の下に表示されているコード全文をコピーして
    上書きして保存しました。

    色々と試したのですが、解決できないので質問させていただきました。
    ご教示いただけますでしょうか。

    • > soda さん

      ご質問いただいた件について、同様の手順で検証を行いました。
      こちらでは問題なく機能しております。検証時のキャプチャ画像をご確認ください。→検証画面キャプチャ

      うまくいかない原因を推測するならば、ディフォルトテーマ「Twenty Eleven」の functions.php へのコードの追記場所はどこにしましたか?
      追記する場所は、functions.php の一番下です。これを一番上などに追記すると動きません。
      ご確認お願いします。

  • soda

    早速のレスポンスありがとうございます!!

    コードは、
    「Twenty Eleven」の functions.php の最下部に追記しています。

    少し私の説明が足りていなかったかも知れませんが、
    私がイメージしていた完成図は、このページ内にあるこの画像のように
    「新規の履歴投稿画面」で、タイトル(title)と本文欄(editor)が表示されず、
    カスタムフィールドテンプレートを一番上に表示されることでした。

    ちなみに、functions.php内の

    ‘supports’ => array(‘title’,’editor’)

    を編集することで、どちらか一方を非表示にすることはできましたが
    両方非表示や、カスタムフィールドテンプレートを上位表示させる
    ことができなかったため、思い悩んでいました。

    また、新規の履歴投稿画面に表示されるカスタムフィールドテンプレートは、
    「カスタムポストタイプ (カンマ区切り):」の欄に「news」と
    設定しているにもかかわらず、プルダウンメニューが表示され、
    その他のテンプレートが選択できてしまう状況になっています。

    hijiriさんの検証結果では正常表示されたとのことですが
    何か考えられる原因やヒントはありませんでしょうか?
    よろしくお願いいたします。

    • > soda さん

      質問の意図を勘違いしておりました。。

      カスタム投稿画面でタイトルと本文の入力欄を非表示にするには、supports オプションの値を以下のようすれはOKです。

      'supports' => array(null)
      

      その場合、投稿一覧画面からも「タイトル」を非表示にしたいと思いますので、以下のコードを追加します。

      function custom_columns($columns) {
      	unset($columns['title']); // タイトル
      	return $columns;
      }
      add_filter( 'manage_edit-news_columns', 'custom_columns' );
      

      さらに、投稿一覧にカスタムフィールドの項目を追加する場合、以下のコードを追加します。
      サンプルのようにフィールド名が「date」のままだと、ディフォルトの「日付」と重複してしまいますので、「news_date」に変更しています。

      function manage_news_columns ($columns) {
      	global $post_type;
      	if ($post_type == 'news') {
      		$columns['news_date'] = '更新日';
      		}
      	return $columns;
      }
      function add_news_column ($column, $post_id) {
      	if ($column == 'news_date') {
      		echo get_post_meta($post_id, 'news_date', true);
      	}
      }
      add_filter('manage_edit-news_columns', 'manage_news_columns');
      add_action('manage_posts_custom_column', 'add_news_column', 10, 2);
      

      ・管理画面の投稿一覧のカスタマイズについては、こちら

      それから、カスタムフィールドテンプレートで複数選択のプルダウンが表示されるのは、複数テンプレートが存在する場合ですので、プラグインの設定画面から、ディフォルトのテンプレートなどが設定されていないか確認してみてください。

  • soda

    hijiriさん、すごいです。
    本当にありがとうございます。

    タイトル非表示という質問に関して、とても細かく丁寧に解説してもらい
    とても感謝しています。

    ちなみになのですが、タイトルを非表示にした後に
    カスタムフィールドテンプレートの設問(テンプレートコンテンツ)に
    入力してもらった値を、その記事のタイトルとして表示させることは
    できませんでしょうか?

    また、回答していただいた文章に

    > カスタムフィールドテンプレートで複数選択のプルダウンが表示されるのは、複数テンプレートが存在する場合

    とありますが、複数あるテンプレートの中で、これだというものを指定して
    表示させることはできないものでしょうか?

    前回も完成イメージの話をさせていただきましたが、私としては
    左メニューのカスタム投稿タイプとして「商品一覧」「メンバー一覧」などを設置し、
    それぞれの投稿タイプの投稿画面で特定のテンプレートがプルダウン無しで表示できれば
    と思っています。
     → 商品一覧の投稿画面には、商品一覧用のテンプレートのみが表示(title,editorなど無し)
     → メンバー一覧の投稿画面には、メンバー一覧用のテンプレートのみが表示(title,editor無し)

    また、前述したように、商品一覧用のテンプレートには、
    「商品名」という項目の入力フォーム(type = text)が実装され、そこに入力したものが
    その記事のタイトルとして、一覧やページに表示されればと思っています。

    本当にわかりやすい解説なのでぜひおしえていただければと思います。
    同じように悩んでいるひとも多いと思うので、ぜひお願いします。

    • > soda さん

      「カスタムフィールドをタイトルとして表示したい」ということですが、これはあくまで表示の問題なので、the_title() で取得した値を”タイトルとして見せる”か、get_post_meta($post->ID, ‘カスタムフィールド名’, true); で取得した値を”タイトルとして見せる”かの違いだけかと思われます。
      投稿一覧画面での表示も同様に、カラム名(上記コードでは「更新日」)を「タイトル」に変更すればよいです。

      カスタム投稿タイプでどのカスタムフィールドテンプレートを適用するかは、プラグインの設定画面で「カスタムポストタイプ (カンマ区切り):」から設定してください。1つのカスタム投稿タイプのみを指定すれば、それ専用になります。
      1対1で専用にした場合でも、プラグイン全体として複数のテンプレートが用意されている場合は、項目1つのプルダウン表示がされるのはプラグインの仕様のようです。

      *今回ご質問いただいた、カスタム投稿タイプとカスタムフィールドの組み合わせによる実践的な内容については、あとでまとめて記事にさせてもらいます。

  • soda

    hijiriさん、どうもありがとうございました。

    > 表示の問題 〜(省略)〜

    ということは確かに考えていました。

    ただ私としては、
    誰が投稿画面を操作しても誤入力がないように完全な投稿フォームにしたかったので、
    タイトルを非表示にして入力フォーム内にタイトルに該当する箇所を埋め込みたかったのと
    1対1となる専用の入力フォームを完璧に実装させたかったんです。。。

    (理由1:デフォルトの状態だと、タイトル欄が未入力だと”タイトルを
         入力してください”と表示されてしまい、できればこの箇所を
         商品一覧のカスタム投稿の場合は、”商品名を入力してください”
         と設定し、実際に入力したものが、ページタイトルになるように
         したかったのです。)
    (理由2:商品一覧のカスタム投稿から新規投稿画面を表示させたのに
         プルダウンで選択したのが(意図せず)メンバー一覧用の
         入力フォームになってしまい、結果的にテレコ状態になる
         可能性があるため など)

    ただ、今回、hijiriさんにこのページで教えていただいた内容で、
    私のスキルを遥かに超えたものが実装できたので、本当に助かりました。

    > カスタム投稿タイプとカスタムフィールドの組み合わせによる実践的な内容については、あとでまとめて記事にさせてもらいます。

    とのことですので、公開される日を楽しみにしております。

    • > soda さん

      参考になれば幸いです。

      soda さんが思い描いていらっしゃる完成形を実装するには、独自プラグイン開発レベルの高度な技術が必要になります。
      その点については、別途機会があれば解説したいと思いますので、お待ち下さいませ。

  • soda

    hijiriさん、
    こんばんは、また新しい質問なんですけれども、、、

    今回事例を出していただいた「更新履歴」のほかに
    別のカスタム投稿タイプを管理画面の左メニューに追加表示させたいと思い、
    functions.phpに対して、まったく同じルールでコード追記してみたところ、
    残念ながら、管理画面が開けなくなってしまいました。
    (コード内の”更新履歴”を”フォトギャラリー”に差し替え、
     後半は register_post_type(‘gallery’,$args);)と追記)

    ちなみに、後に追記した方のコードを削除することで元に戻りました。。。

    複数のカスタム投稿タイプを表示させるには
    どのようなコードを(更新履歴に関するコードを追記した後にさらに)追加すれば
    よろしいのでしょうか?

    よろしくお願いします。

    • > soda さん

      カスタム投稿タイプを複数設置する場合は、以下のようにすれば良いです。

      add_action('init', 'my_custom_post_type');
      function my_custom_post_type() {
      	$labels = array(
      		'name' => _x('更新履歴', 'post type general name'),
      		// 以下省略
      	);
      	$args = array(
      		'labels' => $labels,
      		// 以下省略
      	);
      	$labels2 = array(
      		'name' => _x('フォトギャラリー', 'post type general name'),
      		// 以下省略
      	);
      	$args2 = array(
      		'labels' => $labels2,
      		// 以下省略
      	);
      	register_post_type('news',$args);
      	register_post_type('photo',$args2);
      }
      
  • soda

    hijiri さん
    ありがとうございましたーーー。

  • Pingback: wordpressヒント集 | 株式会社HT-Solutions()

  • Jinjing1025

    はじめまして。
    すごく参考になっています。
    手順通りに行っているのですが
    「4. カスタム投稿タイプを表示する」のコードを記入するファイルは具体的にはどのファイルに当たるのでしょうか?

    • > Jinjing1025さん
      表示させたいページのテンプレートに記述すればOKですよ。home.phpでもpage.phpでもなんでも。query_posts(‘post_type={$post_type}’); でカスタムループを生成しているので、どのテンプレートに記述しても問題ありません。

  • Pingback: インストール後の設定いろいろ | memo()

  • Pingback: WordPressでブログ以外の情報サイトを作るためのプラグイン8個 | 元営業マンのWEB研究メモ()