【実践】WordPressカスタム投稿タイプの作り方|架空SaaSの「導入事例」を例に一通り解説

WordPressで「ブログとは別に、導入事例だけをまとめた一覧ページを作りたい」という場面があります。

実績紹介、セミナー情報、よくある質問なども同じで、ブログ記事と同じ場所に混ぜたくないコンテンツです。

これを実現する仕組みがカスタム投稿タイプとカスタムタクソノミーです。

名前だけは聞いたことあるけど、正直なにがどう違うんか分かってへんねん…。

この記事では、架空のSaaS「タスクノート」のサイトを題材に、導入事例のコーナーをゼロから作る手順を最初から最後まで通しで解説します。

設計の決め方、ファイルの置き場所、登録コード、一覧と詳細のテンプレート、絞り込みまでを順番に扱います。

専門用語が出てくるたびにミニ解説を挟むので、用語に自信がなくても読み進められます。

結構気合入れて書きました。

こんな人におすすめ
「ブログとは別の一覧ページを作りたい」
「カスタム投稿タイプの記事を読んだが、その後どうすればいいか分からない」
「テンプレートファイルの名前の決まりが曖昧なままになっている」
「Web制作を学んでいてカスタム投稿で詰まっている」

なお「タスクノート」は解説のために用意した架空のサービスです。実在する製品ではありません。

目次

この記事で作るもの

今回作るのは、架空のSaaSのサイトがあると仮定して、

そのサービスの既存のブログ(WordPress標準の投稿)はそのまま残したうえで、

それとは別に独立した「導入事例」のコーナーをカスタム投稿で追加する構成です。

ブログの投稿と導入事例のカスタム投稿タイプを左右に並べ、分類とURLが別々になることを示した図
投稿とカスタム投稿タイプの棲み分け

完成すると、次のようなページができあがります。

ページURL内容
導入事例の一覧/case-study/すべての事例をカード形式で表示
導入事例の詳細/case-study/example-corp/1社ぶんの事例ページ
業種で絞った一覧/industry/it/「IT・通信」の事例だけを表示
ブログ(既存)/blog/ などこれまでどおり。事例は混ざらない

管理画面にも「投稿」とは別に「導入事例」のメニューが追加されます。

編集する人は、ブログを書くのと同じ感覚で事例を追加できるようになります。

なぜ「投稿」で代用しないのか

「投稿にカテゴリを1つ足せばいいのでは」と思うかもしれません。

小規模なら実際それでも動きますが、運用が続くほど次の問題が出てきます。

投稿で代用した場合カスタム投稿タイプにした場合
新着一覧やRSSに事例が混ざるブログと完全に分かれる
カテゴリ一覧に事例用の分類が並ぶ専用のタクソノミーで独立管理できる
URLがブログと同じ体系になる/case-study/ のように意味のあるURLにできる
編集者が投稿一覧から事例を探すことになる管理画面のメニューが分かれて迷わない
事例だけの項目(企業名など)を足しづらいその投稿タイプ専用の項目を持たせられる

あとから分離するほうが、最初に分けておくよりはるかに手間がかかります。

「これは記事とは別の種類のコンテンツだ」と言えるなら、最初から分けておくのが安全です。

作る前に決めておく設計

コードを書く前に、名前とURLを決めてしまいます。

あとから変更するとURLが変わってしまうため、ここは慎重に決める価値があります。

【用語ミニ解説】カスタム投稿タイプとは?

WordPressにもともとある「投稿」「固定ページ」に並ぶ、自分で追加できる新しい入れ物のことです。

「導入事例」という投稿タイプを作ると、投稿とは別の一覧・別のURL・別の管理画面メニューを持てるようになります。

【用語ミニ解説】カスタムタクソノミーとは?

タクソノミーは「分類の仕組み」のことです。

実はブログでおなじみの「カテゴリ」も「タグ」も、WordPressの内部ではタクソノミーの一種として扱われています。

それを自分で追加したものがカスタムタクソノミーで、今回は「業種」「企業規模」という2つの分類を作ります。

なお、分類の中に入る個々の項目(「IT・通信」「製造業」など)はタームと呼びます。

タクソノミーが「棚の種類」で、タームが「棚に貼るラベル」みたいなもんか。

今回の設計

項目決めた内容備考
投稿タイプ名case_study半角小文字・20文字以内
URLのスラッグcase-studyURLはハイフンのほうが読みやすい
タクソノミー1industry(業種)階層なし(タグ型)
タクソノミー2company_size(企業規模)階層なし(タグ型)
事例ごとの項目企業名・従業員数・導入時期カスタムフィールドで持たせる

投稿タイプ名には20文字以内・半角小文字の英数字とアンダースコア、ハイフンのみという決まりがあります。

また、postpagecategorytagauthortypeなどはWordPressが内部で使っている予約語なので使えません

タクソノミー名は32文字以内で、使える文字と予約語の注意は同じです。

ファイル構成とディレクトリ構造

作業を始める前に、どのファイルに何を書くのかを先に決めておきます。

ここが曖昧なまま進めると、functions.phpが数百行に膨れ上がって手が付けられなくなります。

子テーマのファイル構成と、登録用ファイルと表示用テンプレートの役割分担を示した図
子テーマのディレクトリ構造

今回のディレクトリ構造

Bash
wp-content/
└── themes/
    ├── parent-theme/           親テーマ(既存テーマ)
    └── tasknote-child/         子テーマ(ここに追加していく)
        ├── style.css
        ├── functions.php       inc/ の各ファイルを読み込むだけにする
        ├── inc/
           ├── post-types.php      カスタム投稿タイプの登録
           ├── taxonomies.php      タクソノミーの登録
           └── meta-fields.php     事例ごとの項目(カスタムフィールド)
        ├── archive-case_study.php  導入事例の一覧ページ
        ├── single-case_study.php   導入事例の詳細ページ
        ├── taxonomy-industry.php   業種で絞り込んだ一覧ページ
        └── template-parts/
            └── content-case_study.php  一覧のカード1枚分
Bash

役割は大きく2つに分かれます。

  • inc/の中 … 投稿タイプや分類をWordPressに登録するためのコード
  • テンプレートファイル … 登録したものを画面に表示するためのコード

この2つは役割がまったく違うので、ファイルを分けておくと後から必ず楽になります

用語ミニ解説:子テーマとは?

既存のテーマを直接編集せず、差分だけを別のテーマとして持たせる仕組みです。

親テーマが更新されても自分の変更が消えないため、テーマにコードを足すときは子テーマを使うのが基本です。

テーマ作りそのものが不安な方は、こちらの記事から読むとスムーズです。

functions.phpは読み込むだけにする

子テーマのfunctions.phpには、処理そのものを書かず読み込みの記述だけを置きます。

PHP
<?php
// 子テーマの functions.php

require_once get_stylesheet_directory() . '/inc/post-types.php';
require_once get_stylesheet_directory() . '/inc/taxonomies.php';
require_once get_stylesheet_directory() . '/inc/meta-fields.php';
PHP

get_stylesheet_directory()は、いま有効になっているテーマ(子テーマ)のディレクトリまでのパスを返す関数です。

親テーマのパスを返すget_template_directory()と混同しやすいので、子テーマ側では前者を使うと覚えてください。

手順1:カスタム投稿タイプ「導入事例」を登録する

ここからが本題です。inc/post-types.phpに、次のコードを書きます。

PHP
<?php
// inc/post-types.php

add_action( 'init', 'tasknote_register_case_study' );

function tasknote_register_case_study() {

    $labels = array(
        'name'          => '導入事例',
        'singular_name' => '導入事例',
        'add_new_item'  => '導入事例を追加',
        'edit_item'     => '導入事例を編集',
        'all_items'     => '導入事例一覧',
    );

    $args = array(
        'labels'        => $labels,
        'public'        => true,
        'has_archive'   => true,
        'menu_position' => 5,
        'menu_icon'     => 'dashicons-awards',
        'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
        'show_in_rest'  => true,
        'rewrite'       => array(
            'slug'       => 'case-study',
            'with_front' => false,
        ),
    );

    register_post_type( 'case_study', $args );
}
PHP

保存して管理画面を開くと、左メニューに「導入事例」が追加されているはずです。

用語ミニ解説:フック(add_action)とは?

フックは「WordPressの処理の途中に、自分のコードを差し込む仕組み」です。

add_action( 'init', '関数名' )は「initというタイミングになったら、この関数を実行してね」という予約にあたります。

投稿タイプの登録はinitより前に実行してはいけないと公式ドキュメントで明記されているため、この形が必須になります。

主要な引数の意味

引数意味
labels管理画面に表示される名前のまとまり
publicサイト上に公開するか。基本はtrue
has_archive一覧ページ(アーカイブ)を作るか。trueにしないと/case-study/が存在しない
menu_position管理画面メニューの並び順。5は「投稿」のすぐ下
menu_iconメニューのアイコン。Dashiconsの名前を指定する
supports使う編集機能。thumbnailを入れるとアイキャッチが使える
show_in_resttrueにするとブロックエディタで編集できる
rewriteURLの形。slugでURLの文字列を指定する

show_in_restを忘れると、編集画面が古いクラシックエディタのままになります。

またwith_frontをfalseにしているのは、パーマリンク設定の接頭辞(/blog/など)をURLの先頭に付けないためです。

登録したら必ずパーマリンクを保存し直す

ここが最初の関門です。

コードを書いただけではURLの解釈ルールが古いままなので、事例ページを開いても404になります。

管理画面の「設定」→「パーマリンク」を開き、そのまま「変更を保存」を押してください

設定を変更する必要はありません。開いて保存するだけでルールが作り直されます。

404で30分悩んだあとにこれ知ったら、ワイ泣いてまうわ…。

登録の最小構成だけをもう少し噛み砕いて知りたい方は、こちらの記事もどうぞ。

手順2:タクソノミー「業種」「企業規模」を登録する

次に、事例を分類するための仕組みを作ります。

inc/taxonomies.phpに次のように書きます。

PHP
<?php
// inc/taxonomies.php

add_action( 'init', 'tasknote_register_case_study_taxonomies' );

function tasknote_register_case_study_taxonomies() {

    // 業種
    register_taxonomy(
        'industry',
        array( 'case_study' ),
        array(
            'label'             => '業種',
            'hierarchical'      => false,
            'public'            => true,
            'show_admin_column' => true,
            'show_in_rest'      => true,
            'rewrite'           => array(
                'slug'       => 'industry',
                'with_front' => false,
            ),
        )
    );

    // 企業規模
    register_taxonomy(
        'company_size',
        array( 'case_study' ),
        array(
            'label'             => '企業規模',
            'hierarchical'      => false,
            'public'            => true,
            'show_admin_column' => true,
            'show_in_rest'      => true,
            'rewrite'           => array(
                'slug'       => 'company-size',
                'with_front' => false,
            ),
        )
    );
}
PHP

第2引数のarray( 'case_study' )が、「この分類をどの投稿タイプで使うか」の指定です。

ここに複数の投稿タイプを並べれば、同じ分類を使い回すこともできます。

用語ミニ解説:hierarchical(階層)とは?

分類に親子関係を持たせるかどうかの設定です。

設定近いもの管理画面の見た目
hierarchical: trueカテゴリチェックボックスで選ぶ。親子を作れる
hierarchical: falseタグ入力欄に打ち込む。親子は作れない

今回の「業種」は親子関係が不要なのでfalseにしています。

ただし編集者に自由入力させたくない場合は、あえてtrueにしてチェックボックス方式にするという選び方もあります。

表記ゆれを防ぎたい運用なら、こちらのほうが安全です。

【用語ミニ解説】スラッグとは?

URLに使われる短い文字列のことです。

業種のスラッグをindustryにしたので、業種ごとの一覧は/industry/it/のようなURLになります。

日本語のままだとURLがエンコードされて長くなるため、タームを追加するときは半角英数のスラッグを手入力するのがおすすめです。

なお、タクソノミーを追加したときもパーマリンクの保存し直しが必要です。

分類を登録したら管理画面から項目を追加する

ここまでできると、管理画面の「導入事例」の下に「業種」「企業規模」というメニューが増えます。

ここで「IT・通信」「製造業」「小売」などのタームをあらかじめ登録しておきます。

show_admin_columnをtrueにしているので、事例の一覧画面にも業種の列が表示されるようになります。

手順3:事例ごとの項目を追加する

導入事例には、本文とは別に「企業名」「従業員数」「導入時期」といった決まった項目があります。

これを本文に手打ちさせると、書く人によって表記がバラバラになり、あとで一覧に出すこともできません

【用語ミニ解説】カスタムフィールドとは?

投稿に本文とは別のデータをぶら下げておく仕組みです。

「この投稿の企業名は◯◯株式会社」というように、名前と値のセットで保存されます。

内部的にはメタデータ(post meta)と呼ばれ、テンプレート側から自由に取り出して表示できます。

項目を登録する

inc/meta-fields.phpに、使う項目を宣言します。

PHP
<?php
// inc/meta-fields.php

add_action( 'init', 'tasknote_register_case_study_meta' );

function tasknote_register_case_study_meta() {

    $fields = array(
        'cs_company_name' => '企業名',
        'cs_employees'    => '従業員数',
        'cs_started_at'   => '導入時期',
    );

    foreach ( $fields as $key => $label ) {
        register_post_meta(
            'case_study',
            $key,
            array(
                'type'              => 'string',
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => 'sanitize_text_field',
                'auth_callback'     => function () {
                    return current_user_can( 'edit_posts' );
                },
            )
        );
    }
}
PHP

register_post_metaで登録しておくと、値の型やサニタイズ(無害化)の方法をまとめて指定できます

auth_callbackは「誰がこの値を編集していいか」の判定で、ここでは投稿を編集できる権限がある人だけに限定しています。

入力欄を編集画面に出す

登録しただけでは編集画面に入力欄は出ません。

ここでは分かりやすさを優先して、企業名だけを例にメタボックスを自作します。

PHP
<?php
// inc/meta-fields.php の続き

add_action( 'add_meta_boxes', 'tasknote_add_case_study_metabox' );

function tasknote_add_case_study_metabox() {
    add_meta_box(
        'tasknote_case_study_fields',
        '事例の基本情報',
        'tasknote_render_case_study_metabox',
        'case_study',
        'side'
    );
}

function tasknote_render_case_study_metabox( $post ) {

    wp_nonce_field( 'tasknote_case_study_save', 'tasknote_case_study_nonce' );

    $company = get_post_meta( $post->ID, 'cs_company_name', true );

    echo '<p><label for="cs_company_name">企業名</label></p>';
    echo '<input type="text" id="cs_company_name" name="cs_company_name" value="' . esc_attr( $company ) . '" class="widefat">';
}

add_action( 'save_post_case_study', 'tasknote_save_case_study_meta' );

function tasknote_save_case_study_meta( $post_id ) {

    // 自動保存や権限のない操作では何もしない
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }
    if ( ! isset( $_POST['tasknote_case_study_nonce'] )
        || ! wp_verify_nonce( $_POST['tasknote_case_study_nonce'], 'tasknote_case_study_save' ) ) {
        return;
    }

    if ( isset( $_POST['cs_company_name'] ) ) {
        update_post_meta(
            $post_id,
            'cs_company_name',
            sanitize_text_field( wp_unslash( $_POST['cs_company_name'] ) )
        );
    }
}
PHP

保存処理では自動保存の除外・権限チェック・nonceの検証という3つの確認を必ず入れます。

nonceは「この送信が本当に自分のサイトの編集画面から来たか」を確かめるための使い捨ての合言葉です。

これを省くと、外部から意図しない更新を受け付けてしまう危険があります。

プラグインを使う選択肢もある

項目が3つ程度なら自作で十分ですが、10個、20個と増えると管理が大変になります。

その場合は、カスタムフィールドを管理画面から設定できるプラグイン(Advanced Custom Fieldsなど)を使う選択肢もあります。

ただしプラグインに依存すると移行時にデータの取り出し方が変わるため、規模と運用体制を見て決めてください。

手順4:導入事例の一覧ページを作る

ここまでで中身の準備は完了です。次は見た目を作る側に移ります。

【用語ミニ解説】テンプレート階層とは?

WordPressが「このURLならこのファイルを使う」と自動で判断する優先順位のルールです。

決められた名前でファイルを置くだけで、WordPressが勝手に見つけて使ってくれます。

逆に言えば、ファイル名が1文字違うだけで読み込まれません

URLごとに使われるテンプレートファイルと、見つからない場合のフォールバック順を示した図
URLとテンプレートファイルの対応

表示したいページファイル名なければ次に探すもの
事例の一覧archive-case_study.phparchive.php → index.php
事例の詳細single-case_study.phpsingle.php → singular.php → index.php
業種で絞った一覧taxonomy-industry.phptaxonomy.php → archive.php → index.php

ファイル名に使うのはURLのスラッグ(case-study)ではなく、投稿タイプ名(case_study)です。

ハイフンとアンダースコアを取り違えるとまったく反映されないので、ここは特に注意してください。

archive-case_study.php を作る

PHP
<?php
// archive-case_study.php

get_header(); ?>

<main class="case-study-archive">

    <h1>導入事例</h1>

    <?php if ( have_posts() ) : ?>

        <div class="case-study-list">
            <?php while ( have_posts() ) : the_post(); ?>
                <?php get_template_part( 'template-parts/content', 'case_study' ); ?>
            <?php endwhile; ?>
        </div>

        <?php the_posts_pagination(); ?>

    <?php else : ?>

        <p>まだ導入事例が登録されていません。</p>

    <?php endif; ?>

</main>

<?php get_footer();
PHP

【用語ミニ解説】ループとは?

while ( have_posts() ) : the_post();の部分はループと呼ばれる、WordPressの中心的な仕組みです。

「表示すべき投稿がまだあるなら、1件ぶん取り出して処理する」を繰り返しています。

どの投稿を取り出すかはURLを見てWordPressが自動で決めているため、一覧側で条件を書く必要はありません。

ループの書き方そのものを詳しく知りたい方は、こちらが参考になります。

カード部分を別ファイルに切り出す

一覧の1枚ぶんはtemplate-parts/content-case_study.phpに分けています。

PHP
<?php
// template-parts/content-case_study.php

$company = get_post_meta( get_the_ID(), 'cs_company_name', true );
$terms   = get_the_terms( get_the_ID(), 'industry' );
?>

<article class="case-study-card">

    <a href="<?php the_permalink(); ?>">

        <?php if ( has_post_thumbnail() ) : ?>
            <?php the_post_thumbnail( 'medium' ); ?>
        <?php endif; ?>

        <?php if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) : ?>
            <span class="case-study-industry"><?php echo esc_html( $terms[0]->name ); ?></span>
        <?php endif; ?>

        <h2><?php the_title(); ?></h2>

        <?php if ( $company ) : ?>
            <p class="case-study-company"><?php echo esc_html( $company ); ?></p>
        <?php endif; ?>

    </a>

</article>
PHP

get_template_part( 'template-parts/content', 'case_study' )は、content-case_study.php を読み込むという意味です。

切り出しておくと、業種別の一覧でも同じカードをそのまま使い回せます。

また、出力時にesc_html()esc_url()を通しているのは入力値をそのまま表示しないための基本的な安全対策です。

手順5:導入事例の詳細ページを作る

詳細ページでは、本文に加えてカスタムフィールドと業種を表示します。

PHP
<?php
// single-case_study.php

get_header(); ?>

<main class="case-study-single">

    <?php while ( have_posts() ) : the_post(); ?>

        <article>

            <h1><?php the_title(); ?></h1>

            <?php
            $company   = get_post_meta( get_the_ID(), 'cs_company_name', true );
            $employees = get_post_meta( get_the_ID(), 'cs_employees', true );
            $industry  = get_the_terms( get_the_ID(), 'industry' );
            ?>

            <dl class="case-study-meta">
                <?php if ( $company ) : ?>
                    <dt>企業名</dt>
                    <dd><?php echo esc_html( $company ); ?></dd>
                <?php endif; ?>

                <?php if ( $employees ) : ?>
                    <dt>従業員数</dt>
                    <dd><?php echo esc_html( $employees ); ?></dd>
                <?php endif; ?>

                <?php if ( ! empty( $industry ) && ! is_wp_error( $industry ) ) : ?>
                    <dt>業種</dt>
                    <dd>
                        <?php foreach ( $industry as $term ) : ?>
                            <a href="<?php echo esc_url( get_term_link( $term ) ); ?>">
                                <?php echo esc_html( $term->name ); ?>
                            </a>
                        <?php endforeach; ?>
                    </dd>
                <?php endif; ?>
            </dl>

            <div class="case-study-body">
                <?php the_content(); ?>
            </div>

        </article>

    <?php endwhile; ?>

</main>

<?php get_footer();
PHP

get_the_terms()は、その投稿に付いている分類(ターム)を配列で取り出す関数です。

タームが1つも付いていないとfalseやエラーが返るため、! empty()! is_wp_error()の両方で確認してから使います。

このチェックを省くと、分類が未設定の事例を開いた瞬間にエラーで真っ白になります

「1件だけ登録忘れてた事例」で本番が落ちるやつやん…気ぃつけよ。

手順6:業種で絞り込んだ一覧を作る

タクソノミーを登録した時点で、絞り込み用のURLはすでに動いています

あとは専用のテンプレートを置くだけで、見た目を整えられます。

taxonomy-industry.php を作る

PHP
<?php
// taxonomy-industry.php

get_header(); ?>

<main class="case-study-archive">

    <h1><?php single_term_title( '業種:' ); ?></h1>

    <?php if ( have_posts() ) : ?>

        <div class="case-study-list">
            <?php while ( have_posts() ) : the_post(); ?>
                <?php get_template_part( 'template-parts/content', 'case_study' ); ?>
            <?php endwhile; ?>
        </div>

        <?php the_posts_pagination(); ?>

    <?php else : ?>

        <p>この業種の導入事例はまだありません。</p>

    <?php endif; ?>

</main>

<?php get_footer();
PHP

一覧とほとんど同じ形で、見出しだけsingle_term_title()に変えています。

これで/industry/it/を開くと「業種:IT・通信」という見出しとともに、その業種の事例だけが並びます。

絞り込みリンクを出力する

読者が業種を選べるように、一覧ページの上部にリンクを並べます。

PHP
<?php
// 業種の絞り込みリンクを出力する(archive-case_study.php などで使う)

$industries = get_terms(
    array(
        'taxonomy'   => 'industry',
        'hide_empty' => true,
    )
);

if ( ! empty( $industries ) && ! is_wp_error( $industries ) ) : ?>

    <ul class="case-study-filter">
        <li><a href="<?php echo esc_url( get_post_type_archive_link( 'case_study' ) ); ?>">すべて</a></li>

        <?php foreach ( $industries as $industry ) : ?>
            <li>
                <a href="<?php echo esc_url( get_term_link( $industry ) ); ?>">
                    <?php echo esc_html( $industry->name ); ?>
                </a>
            </li>
        <?php endforeach; ?>
    </ul>

<?php endif;
PHP

hide_emptyをtrueにすると、事例が1件も紐づいていない業種はリンクに出ません

クリックしても空っぽのページに飛ばされる、という状況を防げます。

手順7:表示件数と並び順を調整する

一覧の表示件数は、初期状態では管理画面の「1ページに表示する最大投稿数」に従います。

ブログは10件、事例は12件のカード並びにしたい、といった場合はpre_get_postsで調整します。

PHP
<?php
// inc/post-types.php の末尾などに追記

add_action( 'pre_get_posts', 'tasknote_case_study_query' );

function tasknote_case_study_query( $query ) {

    // 管理画面とサブクエリには手を出さない
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_post_type_archive( 'case_study' ) || $query->is_tax( 'industry' ) ) {
        $query->set( 'posts_per_page', 12 );
        $query->set( 'orderby', 'date' );
        $query->set( 'order', 'DESC' );
    }
}
PHP

ここで重要なのが最初の2行の条件です。

is_admin()で管理画面を除外し、is_main_query()でそのページの主役となるクエリだけに限定しています。

この確認を省くと、サイドバーの新着一覧や管理画面の投稿一覧まで巻き込んで壊してしまいます

公式ドキュメントでも、この2つをセットで使うことが推奨されています。

つまずきやすいポイント7つ

ここまでの手順で実際に詰まりやすい箇所を、症状別にまとめます。

1. 事例ページを開くと404になる

もっとも多いのがこれです。「設定」→「パーマリンク」を開いて保存し直してください

投稿タイプやタクソノミーを追加・変更したときは、毎回この操作が必要になると考えておくと安全です。

2. 詳細は見られるが一覧(/case-study/)が出ない

has_archiveがfalseのままか、指定を書き忘れています。

trueにしてから、やはりパーマリンクを保存し直してください。

3. 管理画面にメニューが出てこない

functions.phpからのファイル読み込みが効いていないか、PHPのエラーで処理が止まっている可能性があります。

ファイルのパスとスペルを確認し、それでも分からなければデバッグモードでエラー内容を表示させるのが近道です。

4. テンプレートが反映されない

ファイル名をarchive-case-study.phpのようにハイフンで書いていないか確認してください。

正しくは投稿タイプ名そのままのarchive-case_study.phpです。

また、親テーマのフォルダに置いてしまっているケースも多いので、置き場所も合わせて確認しましょう。

5. 同じ名前の固定ページとURLがぶつかる

スラッグがcase-studyの固定ページがすでにあると、どちらか一方しか表示されません。

設計の段階で、既存の固定ページと名前がぶつかっていないかを確認しておいてください。

6. 投稿タイプ名の制限に引っかかっている

投稿タイプ名は20文字以内、タクソノミー名は32文字以内という制限があります。

またpostcategorytypeなどの予約語も使えません。

動かないうえにエラーも分かりにくいので、名前は短く・具体的に付けるのが無難です。

7. 登録コードを消すと事例が消えたように見える

投稿タイプの登録コードを削除すると、管理画面から事例が見えなくなります。

ただしデータそのものはデータベースに残っています

登録コードを戻せば再び表示されるので、慌てて何かを消さないでください。

この性質があるため、投稿タイプの登録はテーマではなくプラグイン側に置くべきという考え方もあります。

テーマを変更する可能性があるサイトでは、その方針も検討する価値があります。

まとめ

カスタム投稿タイプとタクソノミーは、覚えることが多そうに見えてやることは「登録」と「表示」の2つだけです。

登録はregister_post_typeregister_taxonomyをinitで呼ぶこと。

表示は、決められた名前のテンプレートファイルを子テーマに置くこと。

この2本柱さえ押さえておけば、導入事例でも実績紹介でもセミナー情報でも、同じ手順で作れます。

そしてうまくいかないときは、まずパーマリンクを保存し直す。これを覚えておくだけで、無駄に悩む時間が大きく減ります。

登録して、名前どおりのファイル置いて、パーマリンク保存。これだけ覚えて帰るわ!

よくある質問

プラグインとコード、どちらで作るのがいいですか?

長く運用するサイトなら、コードで管理するほうが移行や引き継ぎがしやすくなります。プラグインは設定が手軽な反面、そのプラグインを外すと投稿タイプごと見えなくなるため、依存先が増える点は理解しておく必要があります。

投稿タイプ名はあとから変更できますか?

変更自体は可能ですが、既存のデータが新しい投稿タイプ名と結びつかなくなるため実質的な作り直しになります。URLも変わってしまうので、名前は最初の設計段階で確定させておくのが安全です。

一覧ページのURLを投稿タイプ名と別にできますか?

rewriteのslugを指定すれば別にできます。この記事でも投稿タイプ名はcase_study、URLはcase-studyと分けています。読みやすいURLにしたいときに使う設定です。

ブログのカテゴリを導入事例でも使い回せますか?

register_taxonomyで対象の投稿タイプに既存のcategoryを紐づければ技術的には可能です。ただしブログ側のカテゴリ一覧に事例用の分類が混ざるため、分けて管理したいという当初の目的から外れてしまいます。専用のタクソノミーを作るほうがおすすめです。

SWELLなどの配布テーマでも同じ手順で作れますか?

基本的な流れは同じで、子テーマにファイルを追加していきます。ただしテーマ独自のレイアウト機能があるため、テンプレートの中身は親テーマの書き方に合わせる必要があります。まずは親テーマのarchive.phpを複製し、必要な部分だけ書き換える進め方が確実です。

導入事例をサイト内検索の結果に出したくない場合は?

register_post_typeのexclude_from_searchをtrueにすると、サイト内検索の対象から外れます。ただしpublicをtrueにしている場合は初期値がfalseになるため、明示的に指定する必要があります。検索エンジンからの評価とは別の話なので、混同しないよう注意してください。

参考リンク

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次