本文へスキップ

WordPressのカスタム投稿タイプとカスタムフィールドの作り方!実務で使う最小構成で覚えよう

WordPressで「制作実績」や「お知らせ」のような専用の投稿枠を作る方法です。

通常の投稿にカテゴリーを作って分けている方が多いのではないかと思います。件数が増えてくると、ブログ記事とお知らせが同じ一覧に混ざって管理しづらくなります。

テーマの functions.php に20行ほど書けば作れます。プラグインを使う形と使わない形の両方を載せます。

カスタム投稿タイプの登場人物

コードを書く前に、この記事に出てくるものを整理しておきます。

カスタム投稿タイプ

投稿・固定ページに続く、3つめの入れ物です。「制作実績」という種類を新しく増やすようなイメージですね。

専用の管理画面メニューが増えて、通常の投稿とは別々に管理できるようになります。

カスタムフィールド

1件ごとに追加の入力欄を持たせる仕組みです。制作実績なら「クライアント名」「制作期間」「使用技術」あたりが入ります。

本文のエディタに書くのと違って、値だけを取り出せます。テンプレートの好きな位置に置けるので、レイアウトが崩れません。

functions.php

テーマに機能を足すためのファイルです。カスタム投稿タイプの登録はここに書きます。

書き方を間違えるとサイト全体が真っ白になります。編集する前にバックアップを取っておいてください。

テンプレートファイル

一覧ページ用の archive-works.php と、詳細ページ用の single-works.php です。works の部分に、これから作るカスタム投稿タイプの名前が入ります。

この時点で分からない言葉があっても、深く理解せずに先へ進んで問題ありません。管理画面が実際に変わるのを見てからのほうが、話が早いと思います。

カスタム投稿タイプを作ろう

functions.php に register_post_type を書く

テーマの functions.php の末尾に、次のコードを足します。ファイルの先頭にある <?php は書き足さず、その下に続けてください。

function aoi_register_works_post_type() {
	$labels = array(
		'name'          => '制作実績',
		'singular_name' => '制作実績',
		'add_new_item'  => '制作実績を追加',
		'edit_item'     => '制作実績を編集',
		'all_items'     => '制作実績一覧',
	);

	$args = array(
		'labels'        => $labels,
		'public'        => true,
		'has_archive'   => true,
		'menu_position' => 6,
		'menu_icon'     => 'dashicons-portfolio',
		'supports'      => array( 'title', 'editor', 'thumbnail', 'custom-fields' ),
		'show_in_rest'  => true,
		'rewrite'       => array( 'slug' => 'works', 'with_front' => false ),
	);

	register_post_type( 'works', $args );
}
add_action( 'init', 'aoi_register_works_post_type' );
  • register_post_type() の第1引数 works が投稿タイプの名前です。テンプレートのファイル名もここに合わせます
  • publictrue にすると、管理画面にもサイト側にも表示されます
  • has_archivetrue にすると /works/ の一覧ページが自動で作られます
  • supports は編集画面に出す項目の指定です。custom-fields を入れておかないと、あとで足すカスタムフィールドをブロックエディタから扱えません
  • show_in_resttrue にすると、投稿と同じブロックエディタになります。文章や画像をブロック単位で置いていく、今の編集画面のことです。省くと旧エディタの見た目に戻ります
  • menu_position は管理画面での並び順です。数字が小さいほど上に出ます。投稿が5、メディアが10なので、すでに使われている数字は避けます。6を指定すると投稿のすぐ下に入ります
  • menu_icon はWordPressに最初から入っているアイコンの名前です。dashicons- で始まるものから選べます
  • add_action( 'init', ... ) で実行のタイミングを指定します。WordPressの読み込みが終わった直後に走ります

投稿タイプ名の付け方に気をつけよう

works の部分は自由に決められます。ただし、いくつか決まりがあります。

  • 半角英小文字・数字・ハイフン・アンダースコアのみ。20文字以内
  • post page attachment revision はWordPressが使っています。この名前は指定できません
  • プラグインとぶつかりそうなときは aoi_works のように接頭辞を付けます。URLに出る文字列は rewriteslug で別に決められるので、URLが長くなる心配はありません

パーマリンクを更新して404を防ぐ

コードを保存すると、管理画面の左メニューに「制作実績」が増えます。ただし、この時点で詳細ページを開くと404になります。

カスタム投稿タイプを登録した直後に詳細ページを開くと404になる画面

URLの振り分けルールが古いままだからです。[管理画面]→[設定]→[パーマリンク] を開いて、何も変更せずに「変更を保存」を押してください。

これでルールが作り直され、詳細ページが表示されるようになります。

カスタム投稿タイプで最初に詰まるのがここです。コードは合っているのにページが出ない、という状態になります。

WordPressのパーマリンク設定画面。何も変更せずに「変更を保存」を押す

管理画面にメニューが増えたか確認しよう

左メニューに「制作実績」が出ていれば成功です。試しに1件、タイトルと本文を入れて公開してみてください。

https://example.com/works/ で一覧が、記事ごとのURLで詳細が表示されます。ここまで来れば、あとは中身を足していくだけです。

WordPressの管理画面。左メニューの投稿のすぐ下に「制作実績」が追加された状態

カスタムフィールドを追加しよう

ACF(Advanced Custom Fields)を使う場合

ACFは、管理画面から入力欄を組み立てられるプラグインです。コードを書かずに済むので、納品後にクライアントが自分で更新するサイトに向いています。

[管理画面]→[ACF]→[フィールドグループ]→[新規追加] から作ります。

  • フィールドラベルに「クライアント名」と入れます。フィールド名は client_name のように自動で埋まります
  • フィールドタイプは「テキスト」を選びます
  • 下にある「設定」で、表示条件を「投稿タイプ」「等しい」「制作実績」にします
  • 公開すると、制作実績の編集画面に入力欄が出てきます
ACFのフィールドグループ作成画面。フィールドラベルにクライアント名、フィールド名に client_name を入力した状態

表示条件は画面の下のほうにあります。ここを「制作実績」にしないと、通常の投稿に入力欄が出てしまいます。

ACFのロケーションルール。投稿タイプが制作実績と等しいときに表示する設定

テンプレート側での取り出しは1行です。

<?php echo esc_html( get_field( 'client_name' ) ); ?>

esc_html() は、入力された文字をそのままHTMLとして解釈させないための関数です。フォームやカスタムフィールドから受け取った値には必ず通してください。

プラグインを使わずに書く場合

ACFを入れられない環境では、register_post_meta() で登録します。

function aoi_register_works_meta() {
	register_post_meta( 'works', 'client_name', array(
		'type'              => 'string',
		'single'            => true,
		'show_in_rest'      => true,
		'sanitize_callback' => 'sanitize_text_field',
		'auth_callback'     => function() {
			return current_user_can( 'edit_posts' );
		},
	) );
}
add_action( 'init', 'aoi_register_works_meta' );
  • singletrue にすると「1件につき値は1つ」という扱いになります。省くと配列で返ってきます
  • show_in_resttrue にすると、ブロックエディタから読み書きできます
  • sanitize_callback は保存する前に値を掃除する関数です。省いても動きますが、入力された文字をそのまま保存することになるので入れておきます
  • auth_callback は「誰が編集できるか」の判定です。edit_posts の権限を持つ人だけに絞っています

登録しただけでは入力欄は出てきません。編集画面のパネルから「カスタムフィールド」を表示するか、add_meta_box() で専用の欄を作ります。

ここは書く量が増えます。プラグインを入れられる環境なら、ACFに寄せたほうが早いと思います。

値の取り出しは get_post_meta() です。

<?php echo esc_html( get_post_meta( get_the_ID(), 'client_name', true ) ); ?>

テンプレートファイルで表示しよう

一覧ページ(archive-works.php)

テーマフォルダに archive-works.php を新しく作ります。

<?php get_header(); ?>

<?php if ( have_posts() ) : ?>
	<ul class="p-worksList">
	<?php while ( have_posts() ) : the_post(); ?>
		<li class="p-worksList__item">
			<a href="<?php the_permalink(); ?>">
				<?php the_post_thumbnail( 'medium' ); ?>
				<p><?php the_title(); ?></p>
			</a>
		</li>
	<?php endwhile; ?>
	</ul>
<?php endif; ?>

<?php get_footer(); ?>
  • ファイル名を archive-works.php にすると、/works/ を開いたときだけこのファイルが使われます
  • have_posts()the_post() の組み合わせは、通常の投稿一覧と同じ書き方です
  • the_post_thumbnail( 'medium' )medium は画像サイズの名前です。[管理画面]→[設定]→[メディア] で決まっている中サイズが使われます
  • 取得するコードを自分で書く必要はありません。/works/ を開いた時点で、制作実績だけが入った状態になっています

WP_Query という、条件を指定して投稿を取り出す仕組みもあります。ただし一覧ページでは出番がありません。

archive-works.php で出力した制作実績の一覧ページ

詳細ページ(single-works.php)

<?php get_header(); ?>

<?php while ( have_posts() ) : the_post(); ?>
	<article class="p-works">
		<h1><?php the_title(); ?></h1>
		<?php the_post_thumbnail( 'large' ); ?>
		<div class="p-works__body">
			<?php the_content(); ?>
		</div>
	</article>
<?php endwhile; ?>

<?php get_footer(); ?>

投稿の詳細ページ(single.php)をコピーして、必要な部分だけ書き換える形でも問題ありません。

一覧の表示件数と並び順を変える

一覧ページの件数は、そのままだと [管理画面]→[設定]→[表示設定] の「1ページに表示する最大投稿数」に従います。

制作実績だけ件数を変えたいときは pre_get_posts を使います。表示する内容が決まる前に、条件へ割り込むための仕組みです。

function aoi_works_archive_query( $query ) {
	if ( is_admin() || ! $query->is_main_query() ) {
		return;
	}
	if ( $query->is_post_type_archive( 'works' ) ) {
		$query->set( 'posts_per_page', 12 );
		$query->set( 'orderby', 'date' );
		$query->set( 'order', 'DESC' );
	}
}
add_action( 'pre_get_posts', 'aoi_works_archive_query' );
  • is_admin() で管理画面を除きます。この判定がないと、管理画面の投稿一覧まで12件になります
  • is_main_query() は、そのページの本体かどうかの判定です。サイドバーなどで別に取得しているものを巻き込まないための指定です
  • archive-works.php の中で WP_Query を作り直す書き方もありますが、ページ送りが効かなくなります

カスタムフィールドの値を出力する

値をそのまま出すのではなく、空だったときの分岐を入れておきます。

<?php $client = get_field( 'client_name' ); ?>
<?php if ( $client ) : ?>
	<p class="p-works__client">クライアント:<?php echo esc_html( $client ); ?></p>
<?php endif; ?>

納品後、クライアントが入力欄を空のまま公開することがあります。分岐がないと「クライアント:」というラベルだけがページに残ります。

運用が始まると必ず起きるので、条件分岐は最初から入れておきます。

single-works.php の詳細ページ。カスタムフィールドの値がクライアント:株式会社サンプルとして表示されている

カスタム投稿タイプの仕組み

なぜパーマリンクの更新が必要なのか

WordPressは、URLとページの対応表をデータベースに保存しています。リライトルールと呼ばれるものです。

/works/sample/ を開いたときに、どの投稿を出すかを決めているのがこの表です。

カスタム投稿タイプを登録しただけでは、表は古いまま残っています。パーマリンクの「変更を保存」を押すと表が作り直され、新しいURLが通るようになります。

コードから作り直す flush_rewrite_rules() という関数もあります。ただし毎回のアクセスで呼ぶと重くなるので、init の中には書かないでください。

テーマやプラグインを有効化したタイミングで、1回だけ呼ぶ形になります。

カスタム投稿タイプのテンプレートが探される順番。詳細ページは single-works.php、一覧ページは archive-works.php が先に使われる

テンプレートファイルが選ばれる順番

WordPressは、開かれたURLの種類に応じてテンプレートを上から探します。制作実績の詳細ページなら次の順です。

  • single-works.php
  • single.php
  • singular.php
  • index.php

先に見つかったものが使われます。single-works.php を置くだけで制作実績のデザインを変えられるのは、この順番があるからです。

一覧ページも同じ仕組みです。archive-works.phparchive.phpindex.php の順に探されます。

逆に言うと、archive-works.php を作らなければ既存の archive.php がそのまま使われます。

おわりに

カスタム投稿タイプとカスタムフィールドの、実務で使う最小構成でした!

投稿の種類が2つ3つで済むサイトなら、通常の投稿にカテゴリーを付けるほうが手間は少ないと思います。全部をカスタム投稿タイプにする必要はありません。

ただ、更新の頻度も表示する場所も違うコンテンツが混ざり始めたら、分けておいたほうが後が楽になります。functions.php に20行足すだけで作れるので、ぜひ試してみてください!

Contact

お気軽にご相談ください

X(Twitter)のDM、もしくは本サイトのCONTACTページからご連絡ください。
24時間以内に返信しますので、些細なことでもお気軽にご相談ください。