「商品」「実績」「スタッフ紹介」——投稿・固定ページに続く3つめの記事の種類を作るのがカスタム投稿タイプです。functions.phpにregister_post_type()を書くだけで、管理画面に専用メニューが生まれます。
まずはコピペで動く最小構成から。
function my_register_post_types() {
register_post_type('shohin', [
'label' => '商品',
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-cart',
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'show_in_rest' => true, // ブロックエディタで編集する
]);
}
add_action('init', 'my_register_post_types');これだけで、管理画面に「商品」メニューが追加され、/shohin/が商品一覧のURLになります。
なぜ「投稿」に混ぜないのか
「商品」というカテゴリを作って投稿に入れる手もありますが、性格の違うデータを同じ箱に入れると管理が崩れます。
- 一覧の並び順・表示件数を別々にしたい
- 商品だけに価格・在庫の入力欄を出したい
- ブログのRSSやアーカイブに商品を混ぜたくない
カテゴリは「同じ箱の中の仕分け」、投稿タイプは「箱そのものを増やす」——スケールが1段違います。上のどれかに当てはまるなら、投稿タイプを分ける判断が正解です。
引数の早見表
| 引数 | 意味 | よく使う値 |
|---|---|---|
label / labels | 管理画面の表示名 | '商品'(細かく変えるならlabels配列) |
public | サイトに表示するか | true |
has_archive | 一覧ページを持つか | true('items'で一覧URLを変更も可) |
menu_icon | メニューのアイコン | 'dashicons-cart'など |
menu_position | メニューの位置 | 5(投稿の下)〜25 |
supports | 使う編集機能 | ['title','editor','thumbnail','excerpt'] |
show_in_rest | ブロックエディタ対応 | true |
hierarchical | 親子を持てるか | false(trueで固定ページ型) |
rewrite | URLの形 | ['slug' => 'products', 'with_front' => false] |
taxonomies | 標準の分類を使う | ['category', 'post_tag'] |
exclude_from_search | 検索結果から除く | false |
show_in_nav_menus | メニューに追加できるか | true |
表示名を細かく整える(labels)
labelだけでもほぼ困りませんが、「新規追加」などの文言まで日本語にしたいときはlabelsを使います。
'labels' => [
'name' => '商品',
'singular_name' => '商品',
'add_new_item' => '商品を追加',
'edit_item' => '商品を編集',
'all_items' => '商品一覧',
'search_items' => '商品を検索',
'not_found' => '商品が見つかりません',
],テンプレートを用意する
投稿タイプを登録すると、専用のテンプレートファイルが使えるようになります。ファイル名にルールがあります。
| ファイル名 | 担当ページ |
|---|---|
archive-shohin.php | 商品の一覧(/shohin/) |
single-shohin.php | 商品の詳細ページ |
taxonomy-season.php | 商品に付けた分類の一覧 |
用意しなければarchive.php → index.phpの順に代用されます。まず代用で動かして、必要になったら専用ファイルを作るのが手間の少ない進め方です。
一覧ページのURLを変える
投稿タイプ名をshohinにしつつ、URLは/products/にしたい——という要件はよくあります。
'has_archive' => 'products',
'rewrite' => ['slug' => 'products', 'with_front' => false],has_archiveに文字列を渡すと、一覧のURLをその名前にできるrewrite.slugが詳細ページのURL(/products/商品名/)with_front => falseで、パーマリンク設定の接頭辞(/blog/など)を付けない
投稿タイプ名の決めかた
- 半角小文字の英数字とアンダースコア、20文字以内
postpageattachmentrevisionnav_menu_itemactionorderthemeなどは予約語なので使えない- あとから変えると投稿が全部見えなくなる(データは残るが、その投稿タイプが存在しない扱いになる)ので、最初に決める
迷ったらshohinのようにサイト固有の短い名前にします。汎用的なitemやdataは、プラグインとぶつかる可能性があるので避けるのが無難です。
入力欄を足す
商品なら価格・在庫などの欄が要ります。ACF(SCF)を使えばコード無しで入力欄を追加できます。フィールドグループの「場所」を「投稿タイプ=商品」にすれば、商品の編集画面だけに欄が出ます。
べんりワザACFフィールド別・表示の書き方早見表追加した入力欄をテンプレートに出す書き方はこちら標準機能のカスタムフィールドを使う場合は、supportsに'custom-fields'を足しておきます。
分類(タクソノミー)も足す
商品を「季節」や「ブランド」で分けたいときは、カスタムタクソノミーを追加します。標準のカテゴリ・タグを流用するなら1行です。
'taxonomies' => ['category', 'post_tag'],べんりワザカスタムタクソノミーの作り方(register_taxonomy)専用の分類を作るregister_taxonomyの書き方はこちら一覧をテンプレートに出す
トップページに商品を並べたいときはWP_Queryで取得します。post_typeを指定するのがポイントです。
<?php
$items = new WP_Query([
'post_type' => 'shohin',
'posts_per_page' => 6,
]);
?>
<?php while ($items->have_posts()) : $items->the_post(); ?>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>べんりワザループの外で投稿を取得する方法(WP_Query)WP_Queryの書き方と後始末の理由はこちらfunctions.phpに書く?プラグインに書く?
- テーマの
functions.php——手軽。ただしテーマを変えると投稿タイプが消える(データは残るが管理画面から見えなくなる) - 専用のプラグイン(
wp-content/plugins/my-post-types/に1ファイル)——テーマを変えても残る。長く運用するサイト向き
管理画面から作れるプラグインもありますが、コードで書けば同じ設定をほかのサイトへ持っていけるという利点があります。学習の面でも、まずはコードで書いてみるのがおすすめです。
まとめ
functions.phpでregister_post_type()をinitフックで実行するだけで作れるhas_archiveで一覧、supportsで編集画面の欄、show_in_restでブロックエディタが決まる- テンプレートは
archive-<名前>.php/single-<名前>.php。無ければ既存ファイルが代用される - 404になったらパーマリンク設定を再保存。投稿タイプ名は最初に決めて変えない
種類を分けられるようになると、「1つのWordPressで何種類ものコンテンツを管理する」設計ができるようになります。