WordPressでカスタム投稿タイプを作成する
WordPressには投稿と固定ページが標準で用意されていますが、クライアントが不動産物件リスト、スタッフ名簿、レシピアーカイブなどを必要とする場合、この2つのコンテンツタイプだけでは不十分です。そこでWordPressカスタム投稿タイプの出番です。これは、デフォルト設定を無理に改変することなく、WordPressの既存データモデルにきれいに収まる第一級のコンテンツ構造です。
重要なポイント
- カスタム投稿タイプ(CPT)は、別のテーブルを作成するのではなく、共有の
wp_postsテーブルを拡張します。これにより、管理画面、REST APIエンドポイント、テンプレートルーティングが標準で利用できます。 - コンテンツがテーマの変更に関係なくアクセス可能であるように、CPTは必ずプラグインで登録し、テーマでは登録しないでください。
- ブロックエディターのサポートとREST APIの公開には、
show_in_restをtrueに設定する必要があります。 - リライトルールのフラッシュはプラグイン有効化時のみ実行し、ページロードごとには決して実行しないでください。
カスタム投稿タイプとは?
カスタム投稿タイプ(CPT)は、WordPressに登録する名前付きコンテンツタイプです。名前とは裏腹に、これは別のデータベーステーブルではありません。組み込み投稿タイプもカスタム投稿タイプも、すべてwp_postsテーブルを共有し、post_typeカラムで区別されます。これは重要な概念モデルです。つまり、並列構造を作成するのではなく、既存の構造を拡張しているのです。
デフォルトの投稿タイプには、post、page、attachment、revision、nav_menu_itemがあります。propertyやrecipeのようなCPTを登録すると、WordPressは同じ一貫性でそれを扱います。管理画面、REST APIエンドポイント、URLルーティング、テンプレート階層はすべて同じように機能します。
カスタム投稿タイプ ≠ カスタムフィールド。 CPTはコンテンツのタイプを定義します。カスタムフィールド(ACFまたはメタデータAPIで追加)は、そのコンテンツに付加される追加データを保存します。これらは別々の概念です。
register_post_type()でカスタム投稿タイプを登録する
WordPressカスタム投稿タイプを作成する標準的な方法は、initフックで呼び出されるregister_post_type()関数です。
以下は、シンプルで動作する例です:
add_action( 'init', 'register_property_post_type' );
function register_property_post_type() {
$labels = [
'name' => 'Properties',
'singular_name' => 'Property',
'add_new_item' => 'Add New Property',
'edit_item' => 'Edit Property',
'not_found' => 'No properties found.',
];
$args = [
'labels' => $labels,
'public' => true,
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'rewrite' => [ 'slug' => 'properties' ],
'show_in_rest' => true,
];
register_post_type( 'property', $args );
}
主要な引数の説明
public— CPTを管理画面とフロントエンドで表示可能にします。内部専用タイプの場合はfalseに設定します。labels— 管理画面のすべてのUI文字列を制御します。編集者が混乱しないように、適切に記入する価値があります。supports— 編集画面に表示されるエディター機能を宣言します。一般的な値:title、editor、thumbnail、excerpt、custom-fields。has_archive—/properties/にアーカイブページを有効にします。WordPressは一致するarchive-property.phpテンプレートを探します(またはarchive.phpにフォールバック)。rewrite— URLスラッグを設定します。個別の投稿は/properties/post-name/に表示されます。show_in_rest— これをtrueに設定してください。 これにより、CPTがWordPress REST API経由で公開され、ブロックエディターが投稿タイプで正しく動作するために必要です。これがないと、エディターはクラシックインターフェースにフォールバックします。
Discover how at OpenReplay.com.
プラグイン vs. テーマ:コードはどこに配置すべきか?
これはよくある混乱のポイントです。カスタム投稿タイプはテーマではなく、プラグインで登録してください。
CPT登録がfunctions.phpにあり、クライアントがテーマを変更すると、そのタイプのすべてのコンテンツがアクセス不可能になります。削除されるわけではありませんが、見えなくなります。専用プラグイン(シンプルな1ファイルプラグインでも可)を使用すれば、テーマの変更に関係なくCPTがアクティブなままになります。
リクエストごとにリライトルールをフラッシュしないでください。
flush_rewrite_rules()は一度だけ呼び出してください。register_activation_hook()を介したプラグイン有効化時のみです。initごとにフラッシュすることはパフォーマンス上の問題です。
カスタム投稿タイプのテンプレート階層
WordPressは、単一のCPTエントリに対して次の順序でテンプレートを探します:
single-{post-type}.php(例:single-property.php)single.phpsingular.phpindex.php
アーカイブの場合は、次の順序になります:archive-{post-type}.php → archive.php → index.php。
まとめ
register_post_type()をinitに正しくフックし、show_in_restを有効にし、登録をプラグイン内に配置することで、堅牢でポータブルな基盤が得られます。ここから、カスタムタクソノミー、ACFまたはメタデータAPI経由のメタフィールド、カスタム管理カラムを追加できます。WordPressやテーマの更新時に壊れるようなものに触れる必要はありません。
よくある質問
コンテンツはwp_postsテーブルに残り、削除されません。ただし、WordPressはその投稿タイプを認識しなくなるため、投稿は管理画面とフロントエンドで見えなくなります。プラグインを再有効化すると、すぐにアクセスが復元されます。これが、CPT登録を常にテーマではなく専用プラグインに配置すべき理由です。
はい。同じinitコールバック内でregister_post_type()を複数回呼び出すか、initにフックされた別々のコールバックを使用できます。1つのプラグインが登録できるカスタム投稿タイプの数に制限はありませんが、それぞれ20文字以内の一意の投稿タイプスラッグを持つ必要があります。
これはほぼ常に、リライトルールをフラッシュする必要があることを意味します。WordPress管理画面で「設定」→「パーマリンク設定」にアクセスし、「変更を保存」をクリックしてください。これによりリライトフラッシュがトリガーされます。プラグインの場合は、register_activation_hook()内でflush_rewrite_rules()を呼び出すことで、有効化時に自動的に実行されます。ページロードごとにフラッシュしないでください。
厳密には必要ありませんが、それでも推奨されます。show_in_restをtrueに設定すると、WordPress REST APIを通じて投稿タイプが公開され、ヘッドレス構成、外部統合、将来の互換性に役立ちます。ブロックエディターに切り替えた場合でも、すでに正しく動作します。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.