カスタム投稿タイプとは、WordPressの標準の「投稿」や「固定ページ」とは別に、独自のコンテンツタイプを作成できる機能です。register_post_type()関数を使ってfunctions.phpに登録することで、管理画面に専用メニューが追加され、テンプレートファイルによる表示カスタマイズも可能になります。
この記事では、カスタム投稿タイプの基本概念からregister_post_type()の主要引数、ラベル設定、テンプレート対応、カスタムタクソノミーの紐付け、管理画面のカスタマイズまでを順を追って解説します。WordPressサイトで「実績」「商品」「お知らせ」などの独自コンテンツを管理したい方は、ぜひ参考にしてください。
WordPressのテンプレートファイル全体の仕組みについては、WordPressテーマのテンプレートファイル一覧と役割で詳しく解説しています。
カスタム投稿タイプとは?
WordPressには標準で「投稿(post)」と「固定ページ(page)」という2つのコンテンツタイプがあります。ブログ記事は「投稿」、会社概要やお問い合わせページは「固定ページ」として管理するのが一般的です。
しかし、サイトの規模が大きくなると「実績紹介」「商品情報」「お知らせ」「スタッフ紹介」など、投稿とも固定ページとも異なるコンテンツが必要になります。これらを通常の投稿に混ぜて管理すると、カテゴリが煩雑になり、テンプレートの出し分けも難しくなります。
カスタム投稿タイプを使えば、管理画面のサイドバーに専用メニューが追加され、通常の投稿とは完全に分離して管理できます。テンプレートファイルも専用のものを用意できるため、デザインや表示内容を投稿タイプごとに最適化できます。
標準の投稿タイプとの比較
| 項目 | 投稿(post) | 固定ページ(page) | カスタム投稿タイプ |
|---|---|---|---|
| 用途 | ブログ記事・ニュース | 会社概要・お問い合わせ等 | 実績・商品・お知らせ等 |
| 時系列の並び | あり | なし | 設定次第 |
| カテゴリ・タグ | あり(標準) | なし | カスタムタクソノミーで対応 |
| テンプレート階層 | single.php | page.php | single-{post_type}.php |
| アーカイブ | あり | なし | has_archiveで設定 |
| 管理画面メニュー | 「投稿」 | 「固定ページ」 | 専用メニュー追加 |
よく使われるカスタム投稿タイプの例
- 実績・ポートフォリオ(works): 制作実績や事例紹介を一覧・個別表示
- 商品(products): ECサイトほどの機能は不要だが、商品情報を掲載したい場合
- お知らせ(news): ブログとは別にお知らせ・プレスリリースを管理
- スタッフ紹介(staff): チームメンバーのプロフィールを管理
- 物件情報(properties): 不動産サイトの物件データ管理
- イベント(events): セミナーやイベント情報を日付管理
register_post_typeの基本
カスタム投稿タイプは、functions.phpにregister_post_type()関数を記述して登録します。initフックに紐付けるのが基本パターンです。
最小構成のコード
まずは最小限の引数で動作するコードを見てみましょう。以下のコードをfunctions.phpに追加すると、管理画面に「実績」メニューが表示されます。
function my_register_post_types() {
register_post_type( 'works', array(
'labels' => array(
'name' => '実績',
'singular_name' => '実績',
),
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-portfolio',
'supports' => array( 'title', 'editor', 'thumbnail' ),
'show_in_rest' => true,
) );
}
add_action( 'init', 'my_register_post_types' );このコードのポイントは以下の通りです。
- 第1引数
'works'は投稿タイプのスラッグ(20文字以内、小文字英数字とアンダースコア) 'public' => trueでフロントエンドと管理画面の両方に表示'has_archive' => trueでアーカイブページ(一覧ページ)を有効化'show_in_rest' => trueはブロックエディタ(Gutenberg)を使うために必須'supports'で使用するエディタ機能を指定
functions.phpのカスタマイズ全般については、functions.php便利コード集も参考にしてください。
主要引数の一覧
register_post_type()の第2引数で指定できる主要な引数は以下の通りです。WordPress公式ドキュメント(Developer Resources)に基づいています。
| 引数 | 型 | デフォルト | 説明 |
|---|---|---|---|
labels | array | – | 管理画面に表示されるラベルの配列 |
public | bool | false | フロントエンド・管理画面・クエリで使用可能にする |
has_archive | bool/string | false | アーカイブページを有効にする |
show_in_rest | bool | false | REST APIとブロックエディタで使用可能にする |
supports | array | [‘title’, ‘editor’] | サポートする機能(title, editor, thumbnail, excerpt等) |
menu_icon | string | null | 管理画面メニューのアイコン(Dashiconsクラス名またはSVG) |
menu_position | int | null | 管理画面メニューの表示位置(5=投稿の下、20=固定ページの下 等) |
rewrite | array/bool | true | パーマリンク構造の設定(slugキーでURLスラッグ変更可能) |
capability_type | string | ‘post’ | 権限の基準となる投稿タイプ |
hierarchical | bool | false | trueで固定ページのように親子関係を持てる |
taxonomies | array | [] | 紐付けるタクソノミーのスラッグ配列 |
publicly_queryable | bool | publicの値 | フロントエンドでクエリ可能にする |
exclude_from_search | bool | !publicの値 | サイト内検索から除外する |
supportsで指定できる機能
supports引数に渡す配列で、投稿編集画面で使える機能を選択できます。
| 値 | 機能 |
|---|---|
title | タイトル入力欄 |
editor | 本文エディタ |
thumbnail | アイキャッチ画像 |
excerpt | 抜粋 |
custom-fields | カスタムフィールド |
page-attributes | ページ属性(メニューの順序、親ページ) |
comments | コメント |
revisions | リビジョン |
author | 投稿者の選択 |
ラベルの設定
labels配列を適切に設定すると、管理画面のメニューやボタン、メッセージが日本語で自然に表示されます。最小構成ではnameとsingular_nameだけでも動作しますが、実務ではすべてのラベルを設定するのがおすすめです。
labels配列の各キー
| キー | 表示箇所 | 設定例(実績の場合) |
|---|---|---|
name | メニュー名・一覧ページタイトル | 実績 |
singular_name | 単数形の名前 | 実績 |
add_new | 「新規追加」メニュー | 新規追加 |
add_new_item | 新規追加画面のタイトル | 新しい実績を追加 |
edit_item | 編集画面のタイトル | 実績を編集 |
new_item | 新規アイテム | 新しい実績 |
view_item | 「表示」リンク | 実績を表示 |
view_items | 「一覧を表示」リンク | 実績一覧を表示 |
search_items | 検索ボタン | 実績を検索 |
not_found | 見つからない時のメッセージ | 実績が見つかりません |
not_found_in_trash | ゴミ箱に見つからない時 | ゴミ箱に実績はありません |
all_items | サブメニュー「すべての○○」 | すべての実績 |
完全なラベル設定の実装例
function my_register_post_types() {
$labels = array(
'name' => '実績',
'singular_name' => '実績',
'add_new' => '新規追加',
'add_new_item' => '新しい実績を追加',
'edit_item' => '実績を編集',
'new_item' => '新しい実績',
'view_item' => '実績を表示',
'view_items' => '実績一覧を表示',
'search_items' => '実績を検索',
'not_found' => '実績が見つかりません',
'not_found_in_trash' => 'ゴミ箱に実績はありません',
'all_items' => 'すべての実績',
'menu_name' => '実績',
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-portfolio',
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions' ),
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'works', 'with_front' => false ),
);
register_post_type( 'works', $args );
}
add_action( 'init', 'my_register_post_types' );'rewrite' => array( 'slug' => 'works', 'with_front' => false )の設定により、URLはhttps://example.com/works/記事スラッグ/の形式になります。'with_front' => falseを指定すると、パーマリンク設定の接頭辞(例: /blog/)が付かなくなります。
なお、register_post_type()のコードを変更した後は、管理画面の「設定」→「パーマリンク設定」で「変更を保存」をクリックして、リライトルールを更新してください。これを忘れると404エラーになることがあります。
アーカイブとテンプレート対応
カスタム投稿タイプを登録したら、フロントエンドの表示用にテンプレートファイルを用意します。WordPressのテンプレート階層に沿って、投稿タイプ専用のテンプレートを作成できます。
has_archiveの設定
'has_archive' => trueを設定すると、投稿タイプのスラッグがそのままアーカイブページのURLになります。例えば投稿タイプworksの場合、https://example.com/works/がアーカイブページになります。
文字列を指定すると、そのスラッグがアーカイブURLに使われます。
// アーカイブURLが /portfolio/ になる
'has_archive' => 'portfolio',テンプレートファイルの対応関係
カスタム投稿タイプに対応するテンプレートファイルは、WordPressのテンプレート階層に基づいて以下の順で読み込まれます。
| ページ種別 | テンプレート優先順位 | URL例 |
|---|---|---|
| 個別記事 | single-works.php → single.php → singular.php → index.php | /works/my-project/ |
| アーカイブ(一覧) | archive-works.php → archive.php → index.php | /works/ |
アーカイブテンプレートの詳細な使い方は、archive.phpの使い方とカスタマイズで解説しています。
single-{post_type}.phpの実装例
投稿タイプworksの個別記事テンプレートとして、single-works.phpを作成します。
<?php get_header(); ?>
<main class="site-main">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<article class="works-single">
<h1><?php the_title(); ?></h1>
<?php if ( has_post_thumbnail() ) : ?>
<div class="works-thumbnail">
<?php the_post_thumbnail( 'large' ); ?>
</div>
<?php endif; ?>
<div class="works-content">
<?php the_content(); ?>
</div>
</article>
<?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>archive-{post_type}.phpの実装例
投稿タイプworksのアーカイブテンプレートとして、archive-works.phpを作成します。
<?php get_header(); ?>
<main class="site-main">
<h1>実績一覧</h1>
<?php if ( have_posts() ) : ?>
<div class="works-grid">
<?php while ( have_posts() ) : the_post(); ?>
<article class="works-card">
<a href="<?php the_permalink(); ?>">
<?php if ( has_post_thumbnail() ) : ?>
<?php the_post_thumbnail( 'medium' ); ?>
<?php endif; ?>
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
</a>
</article>
<?php endwhile; ?>
</div>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p>実績がまだありません。</p>
<?php endif; ?>
</main>
<?php get_footer(); ?>テンプレートファイル全体の階層構造や仕組みについては、WordPressテーマのテンプレートファイル一覧と役割で体系的にまとめています。WordPress関数の使い方はWordPress関数一覧も参照してください。
カスタムタクソノミーの登録
カスタム投稿タイプには、標準の「カテゴリ」や「タグ」は紐付いていません。投稿を分類したい場合は、register_taxonomy()でカスタムタクソノミー(独自の分類)を登録し、投稿タイプに紐付けます。
register_taxonomyの基本
以下の例では、投稿タイプworksに対して「実績カテゴリ」というカスタムタクソノミーを登録しています。
function my_register_taxonomies() {
$labels = array(
'name' => '実績カテゴリ',
'singular_name' => '実績カテゴリ',
'search_items' => '実績カテゴリを検索',
'all_items' => 'すべての実績カテゴリ',
'edit_item' => '実績カテゴリを編集',
'update_item' => '実績カテゴリを更新',
'add_new_item' => '新しい実績カテゴリを追加',
'new_item_name' => '新しい実績カテゴリ名',
'menu_name' => '実績カテゴリ',
);
register_taxonomy( 'works_category', 'works', array(
'labels' => $labels,
'hierarchical' => true,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'works-category' ),
) );
}
add_action( 'init', 'my_register_taxonomies' );ポイントは以下の通りです。
- 第1引数はタクソノミーのスラッグ(
works_category) - 第2引数は紐付ける投稿タイプ(
works)。配列で複数指定も可能 'hierarchical' => trueでカテゴリ型(チェックボックスUI)、falseでタグ型(テキスト入力UI)'show_in_rest' => trueでブロックエディタのサイドバーに表示
カテゴリ型とタグ型の違い
| 項目 | カテゴリ型(hierarchical: true) | タグ型(hierarchical: false) |
|---|---|---|
| 親子関係 | あり | なし |
| 管理画面のUI | チェックボックス | テキスト入力(タグ追加形式) |
| 用途例 | 実績の種類(Webサイト、アプリ等) | 使用技術(WordPress、React等) |
タクソノミーをテンプレートで表示する
投稿に紐付いたタクソノミーのタームをテンプレート内で表示するには、get_the_terms()を使います。
$terms = get_the_terms( get_the_ID(), 'works_category' );
if ( $terms && ! is_wp_error( $terms ) ) {
echo '<div class="works-categories">';
foreach ( $terms as $term ) {
printf(
'<a href="%s" class="works-category-tag">%s</a>',
esc_url( get_term_link( $term ) ),
esc_html( $term->name )
);
}
echo '</div>';
}管理画面のカスタマイズ
カスタム投稿タイプを登録しただけでは、管理画面の一覧に表示される情報はタイトルと日付のみです。投稿タイプに合わせてカラムを追加したり、メタボックスでカスタムフィールドを入力できるようにすると、運用効率が大幅に向上します。
管理画面一覧にカラムを追加
投稿一覧にアイキャッチ画像やカスタムフィールドの値を表示するには、manage_{post_type}_posts_columnsフィルターとmanage_{post_type}_posts_custom_columnアクションを使います。
// カラムのヘッダーを定義
function my_works_columns( $columns ) {
$new_columns = array(
'cb' => $columns['cb'],
'thumbnail' => 'アイキャッチ',
'title' => $columns['title'],
'client' => 'クライアント',
'taxonomy-works_category' => '実績カテゴリ',
'date' => $columns['date'],
);
return $new_columns;
}
add_filter( 'manage_works_posts_columns', 'my_works_columns' );
// カラムの内容を出力
function my_works_column_content( $column, $post_id ) {
switch ( $column ) {
case 'thumbnail':
if ( has_post_thumbnail( $post_id ) ) {
echo get_the_post_thumbnail( $post_id, array( 80, 80 ) );
} else {
echo '—';
}
break;
case 'client':
$client = get_post_meta( $post_id, '_works_client', true );
echo esc_html( $client ? $client : '—' );
break;
}
}
add_action( 'manage_works_posts_custom_column', 'my_works_column_content', 10, 2 );メタボックスの追加
投稿編集画面にカスタム入力欄を追加するには、add_meta_box()を使います。以下は「クライアント名」と「URL」を入力するメタボックスの例です。
// メタボックスを追加
function my_works_meta_box() {
add_meta_box(
'works_details',
'実績の詳細',
'my_works_meta_box_callback',
'works',
'normal',
'high'
);
}
add_action( 'add_meta_boxes', 'my_works_meta_box' );
// メタボックスのHTML出力
function my_works_meta_box_callback( $post ) {
wp_nonce_field( 'my_works_meta_box', 'my_works_meta_box_nonce' );
$client = get_post_meta( $post->ID, '_works_client', true );
$url = get_post_meta( $post->ID, '_works_url', true );
?>
<p>
<label for="works_client">クライアント名</label><br>
<input type="text" id="works_client" name="works_client"
value="<?php echo esc_attr( $client ); ?>"
style="width: 100%;">
</p>
<p>
<label for="works_url">サイトURL</label><br>
<input type="url" id="works_url" name="works_url"
value="<?php echo esc_attr( $url ); ?>"
style="width: 100%;">
</p>
<?php
}
// メタボックスのデータを保存
function my_works_save_meta( $post_id ) {
if ( ! isset( $_POST['my_works_meta_box_nonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( $_POST['my_works_meta_box_nonce'], 'my_works_meta_box' ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['works_client'] ) ) {
update_post_meta( $post_id, '_works_client', sanitize_text_field( $_POST['works_client'] ) );
}
if ( isset( $_POST['works_url'] ) ) {
update_post_meta( $post_id, '_works_url', esc_url_raw( $_POST['works_url'] ) );
}
}
add_action( 'save_post_works', 'my_works_save_meta' );メタボックスはクラシックエディタ向けのUIです。ブロックエディタではサイドバーパネル(PluginDocumentSettingPanel)で実装する方法もありますが、show_in_restでカスタムフィールドをREST API対応にすれば、メタボックスでもブロックエディタで使用できます。
カスタムフィールドについてさらに詳しく知りたい場合は、WordPressカスタムフィールド解説を参照してください。また、ACF(Advanced Custom Fields)を使った管理画面のカスタマイズはACFで管理画面カスタマイズで解説しています。
ダッシュアイコンの選び方
menu_icon引数には、WordPressに組み込まれているDashiconsのクラス名を指定できます。よく使われるアイコンをいくつか紹介します。
| Dashiconsクラス | アイコン用途 |
|---|---|
dashicons-portfolio | ポートフォリオ・実績 |
dashicons-cart | 商品・EC |
dashicons-megaphone | お知らせ・告知 |
dashicons-groups | スタッフ・チーム |
dashicons-building | 物件・不動産 |
dashicons-calendar | イベント・スケジュール |
dashicons-star-filled | レビュー・評価 |
dashicons-book | 書籍・マニュアル |
利用可能なすべてのDashiconsは、WordPress公式のDashicons一覧ページで確認できます。SVGやBase64エンコードした画像を指定することも可能です。
実践的な完全コード
ここまでの内容をまとめた、実務で使える完全なコードを紹介します。カスタム投稿タイプとカスタムタクソノミーの登録、カラム追加、メタボックスをひとつのファイルにまとめています。
<?php
/**
* カスタム投稿タイプ「実績(works)」の登録
* functions.php から require して使用する
*/
// カスタム投稿タイプの登録
function my_register_post_types() {
$labels = array(
'name' => '実績',
'singular_name' => '実績',
'add_new' => '新規追加',
'add_new_item' => '新しい実績を追加',
'edit_item' => '実績を編集',
'new_item' => '新しい実績',
'view_item' => '実績を表示',
'view_items' => '実績一覧を表示',
'search_items' => '実績を検索',
'not_found' => '実績が見つかりません',
'not_found_in_trash' => 'ゴミ箱に実績はありません',
'all_items' => 'すべての実績',
'menu_name' => '実績',
);
register_post_type( 'works', array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-portfolio',
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions' ),
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'works', 'with_front' => false ),
) );
}
add_action( 'init', 'my_register_post_types' );
// カスタムタクソノミーの登録
function my_register_taxonomies() {
register_taxonomy( 'works_category', 'works', array(
'labels' => array(
'name' => '実績カテゴリ',
'singular_name' => '実績カテゴリ',
'search_items' => '実績カテゴリを検索',
'all_items' => 'すべての実績カテゴリ',
'edit_item' => '実績カテゴリを編集',
'update_item' => '実績カテゴリを更新',
'add_new_item' => '新しい実績カテゴリを追加',
'new_item_name' => '新しい実績カテゴリ名',
'menu_name' => '実績カテゴリ',
),
'hierarchical' => true,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'works-category' ),
) );
register_taxonomy( 'works_tag', 'works', array(
'labels' => array(
'name' => '実績タグ',
'singular_name' => '実績タグ',
'search_items' => '実績タグを検索',
'all_items' => 'すべての実績タグ',
'edit_item' => '実績タグを編集',
'update_item' => '実績タグを更新',
'add_new_item' => '新しい実績タグを追加',
'new_item_name' => '新しい実績タグ名',
'menu_name' => '実績タグ',
),
'hierarchical' => false,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'works-tag' ),
) );
}
add_action( 'init', 'my_register_taxonomies' );このコードをfunctions.phpからrequireするか、直接記述して使用します。ファイルを分ける場合は、inc/post-types.phpのようなファイルに記述し、functions.phpからrequire get_template_directory() . '/inc/post-types.php';で読み込むのがおすすめです。
よくある質問
Q. カスタム投稿タイプを追加したのに404エラーが表示されます。どうすればいいですか?
管理画面の「設定」→「パーマリンク設定」で「変更を保存」をクリックしてください。register_post_type()で投稿タイプを追加・変更した際は、WordPressのリライトルールを更新する必要があります。コードを変更するたびにこの操作を行うことで404エラーが解消されます。
Q. カスタム投稿タイプのスラッグに使えない文字はありますか?
スラッグは20文字以内で、小文字の英数字とアンダースコア(_)のみ使用できます。ハイフン(-)は使用可能ですが、関数内部での扱いを考慮してアンダースコアが推奨されます。また、WordPressの予約語(post, page, attachment, revision, nav_menu_item等)は使用できません。
Q. プラグインなしでカスタム投稿タイプを作成できますか?
はい、functions.phpにregister_post_type()を記述するだけでプラグインなしで作成できます。ただし、テーマを変更するとカスタム投稿タイプの登録が失われるため、テーマに依存しない汎用的な投稿タイプの場合は、独自プラグインとして実装するか、CPT UIなどのプラグインを使う方法も検討してください。
Q. show_in_restをtrueにしないとどうなりますか?
show_in_restがfalse(デフォルト)の場合、ブロックエディタ(Gutenberg)が使えず、クラシックエディタでの編集になります。また、REST APIからアクセスできないため、外部アプリケーションやJavaScriptからの操作もできません。WordPress 5.0以降ではブロックエディタが標準のため、特別な理由がない限りtrueに設定することをおすすめします。
Q. 既存の投稿をカスタム投稿タイプに変換できますか?
WordPressのデータベース上では、投稿タイプはwp_postsテーブルのpost_typeカラムで管理されています。直接データベースを操作するか、「Post Type Switcher」などのプラグインを使うことで、既存の投稿を別の投稿タイプに変換できます。ただし、テンプレートやカスタムフィールドの整合性に注意が必要です。変換前に必ずバックアップを取ってください。
Q. カスタム投稿タイプにカテゴリやタグを使うことはできますか?
はい、register_post_type()のtaxonomies引数にarray(‘category’, ‘post_tag’)を指定すれば、通常の投稿と同じカテゴリやタグを使用できます。ただし、通常の投稿とカテゴリが混在するため、管理が複雑になりがちです。一般的にはregister_taxonomy()で専用のカスタムタクソノミーを作成する方法が推奨されます。
Q. カスタム投稿タイプの投稿をトップページやサイト内検索に含めるにはどうしますか?
サイト内検索に含めるには、exclude_from_searchをfalse(publicがtrueなら自動的にfalse)に設定します。トップページのメインクエリに含めるには、pre_get_postsフックを使ってpost_typeパラメータにカスタム投稿タイプを追加します。例: $query->set(‘post_type’, array(‘post’, ‘works’));のように指定します。
まとめ
カスタム投稿タイプを使いこなすことで、WordPressサイトのコンテンツ管理の自由度が大きく広がります。この記事で解説した内容をまとめると、以下のステップになります。
register_post_type()で投稿タイプを登録(initフックに紐付け)labels配列で管理画面の日本語表示を設定has_archiveを有効にし、archive-{post_type}.phpとsingle-{post_type}.phpでテンプレートを作成register_taxonomy()で専用のカスタムタクソノミーを登録- 必要に応じてカラム追加・メタボックスで管理画面を最適化
- パーマリンク設定の「変更を保存」でリライトルールを更新
カスタム投稿タイプはWordPressテーマ開発の中核となる機能です。テンプレートファイルの階層構造と組み合わせることで、あらゆる種類のWebサイトを構築できます。テンプレートファイル全体の構成については、WordPressテーマのテンプレートファイル一覧と役割もあわせてご覧ください。
