日付形式のカスタムフィールドを元にどのようなアーカイブページを作るか

作成日:

WordPressでイベント投稿を作成する際に、カスタムフィールドで「開催日」などの日付を入力するように設計することになると思いますが、さて、「投稿日」ではなく、「開催日」をベースに投稿をアーカイブ(「2019年1月のイベント」等)として表示するにはどうするかを悩みました。

一つ目の方法は、そもそもの投稿日を起点としているクエリを改変して、カスタムフィールドの「開催日」に入れ替えるという方法。

それには以下の記事が参考になりそうです。

Archive Listings Filtered by Date Values in a Custom Field/Post Meta? https://wordpress.stackexchange.com/questions/5800/archive-listings-filtered-by-date-values-in-a-custom-field-post-meta

カスタムフィールド/投稿メタの日付値で絞り込まれたアーカイブリスト

ただ、クエリの改変はその後の仕様変更に対するリスクも高まるのと、基本的にイベントの開催日は現時点よりも未来の日付になるので、本来は予約投稿となるのが正しく解釈出来るかテストをしなくてはならないのが面倒に。

また、常時「開催日」順に投稿クエリが並び替えられることになるので、「最近追加したイベント」という投稿リストも使えなくなる可能性があります。

そこで、まぁ、色々と考えた結果、イベントの保存時に開催日を元にカスタムタクソノミー「イベントアーカイブ」に

  • 2019年1月のイベント
  • 2019年2月のイベント
  • 2019年3月のイベント
  • 2019年4月のイベント

のようなタームを追加する、という方法です。

これでタームのリンクがそのままアーカイブページになるので、煩わしいコードも書かなくても良いはず。

まずはカスタム投稿(event)とカスタムタクソノミー(event_archive)の登録

PHP functions.php
$event_labels  = array(
	'name'               => 'イベント',
	'singular_name'      => 'イベント',
	'menu_name'          => 'イベント',
	'name_admin_bar'     => 'イベント',
	'add_new'            => '新規追加',
	'add_new_item'       => '新規イベントを追加',
	'new_item'           => '新規イベント',
	'edit_item'          => 'イベントの編集',
	'view_item'          => 'イベントの表示',
	'all_items'          => 'すべてのイベント',
	'search_items'       => 'イベントの検索',
	'not_found'          => 'イベントが見つかりませんでした。',
	'not_found_in_trash' => 'ゴミ箱にイベントが見つかりませんでした。',
);
$event_support = array(
	'title',
	'revisions',
	'thumbnail',
	'editor',
	'excerpt',
	'comments',
);
register_post_type(
	'event',
	array(
		'labels'              => $event_labels,
		'public'              => true,
		'hierarchical'        => false,
		'has_archive'         => true,
		'menu_icon'           => 'dashicons-calendar-alt',
		'exclude_from_search' => false,
		'show_ui'             => true,
		'show_in_menu'        => true,
		'show_in_rest'        => true,
		'rest_base'           => 'event',
		'menu_position'       => 6,
		'rewrite'             => array( 'slug' => 'event' ),
		'supports'            => $event_support,
	)
);
$event_archive_labels = array(
	'name'                       => 'イベントアーカイブ',
	'singular_name'              => 'イベントアーカイブ',
	'search_items'               => 'イベントアーカイブを検索',
	'popular_items'              => '人気のイベントアーカイブ',
	'all_items'                  => 'すべてのイベントアーカイブ',
	'edit_item'                  => 'イベントアーカイブの編集',
	'update_item'                => 'イベントアーカイブの更新',
	'add_new_item'               => '新規イベントアーカイブを追加',
	'new_item_name'              => '新規イベントアーカイブ名',
	'separate_items_with_commas' => 'イベントアーカイブが複数ある場合はコンマで区切ってください',
	'add_or_remove_items'        => 'イベントアーカイブの追加もしくは削除',
	'choose_from_most_used'      => 'よく使われているイベントアーカイブから選択',
	'menu_name'                  => 'イベントアーカイブ',
);
register_taxonomy(
	'event_archive',
	'event',
	array(
		'labels'                => $event_archive_labels,
		'hierarchical'          => false,
		'show_ui'               => true,
		'show_admin_column'     => true,
		'show_in_rest'          => true,
		'rest_base'             => 'event_archive',
		'update_count_callback' => '_update_post_term_count',
		'query_var'             => true,
		'rewrite'               => array(
			'slug' => 'event_archive',
		),
	)
);

次に保存時のフックを

PHP functions.php
function presave_option() {
	global $post;
	if ( 'event' === $post->post_type ) {
		$from_date    = get_post_meta( $post->ID, 'from_date', true );
		$archive_name = date( 'Y年n月', strtotime( $from_date ) ) . 'のイベント';
		$archive_slug = date( 'Y-n', strtotime( $from_date ) );
		if ( ! term_exists( $archive_slug, 'event_archive' ) ) {
			wp_insert_term( $archive_name, 'event_archive', $args = array( 'slug' => $archive_slug ) );
		}
		wp_delete_object_term_relationships( $post->ID, 'event_archive' );
		wp_set_object_terms( $post->ID, array( $archive_slug ), 'event_archive', true );
	}
}
add_action( 'save_post', 'presave_option', 999 );

詳しく説明すると、

PHP functions.php [4]
		$from_date    = get_post_meta( $post->ID, 'from_date', true );
で開催日のカスタムフィールド「from_date」を取得

PHP functions.php [5-6]
		$archive_name = date( 'Y年n月', strtotime( $from_date ) ) . 'のイベント';
		$archive_slug = date( 'Y-n', strtotime( $from_date ) );
$archive_slug = date( 'Y-n', strtotime( $from_date ) );[/php]で登録するイベントアーカイブのターム名、スラグを作成

PHP functions.php [7-9]
		if ( ! term_exists( $archive_slug, 'event_archive' ) ) {
			wp_insert_term( $archive_name, 'event_archive', $args = array( 'slug' => $archive_slug ) );
		}
で、未登録のタームだったら新規にイベントアーカイブのタームを作成

PHP functions.php [10]
		wp_delete_object_term_relationships( $post->ID, 'event_archive' );
で、一旦イベント投稿に関連付けられているイベントアーカイブタームをすべて解除(開催日が変更になった場合の為)

PHP functions.php [11]
		wp_set_object_terms( $post->ID, array( $archive_slug ), 'event_archive', true );
で、イベント投稿にイベントタームを追加

となります。

書きながら気づきましたが、イベント終了日が次の月になった場合はイベントアーカイブのタームをさらに追加する必要があるな、と。これに対応すればむしろ最初に案より管理が便利になります。

もう少し改良してみよう。

物草 灸太郎

WordPressでホームページを制作しつつ、休日は畑を耕したりDIYを楽しんでいます。

コメント

日付形式のアーカイブページを階層タクソノミーに変更 – モノグサにお灸 さん
[…] 日付形式のカスタムフィールドを元にどのようなアーカイブページを作るか […]
2019年1月27日 11:08 PM 返信

コメントをどうぞ

  • メールアドレスが公開されることはありません。
  • コメント欄にURLは入力できません。
  • このサイトはreCAPTCHAによって保護されており、Googleのプライバシーポリシー利用規約が適用されます。