ウェビングスタジオのサイトはWordPressテーマ「Snow Monkey」で制作していますが、投稿(ブログ)と固定ページとは別に「活動記録」という、カスタム投稿タイプで作成したコンテンツがあります。
このサイト以外で発信した投稿や技術情報を記録している、シンプルなリンク集です。
WordPressの既存テーマを案件に採用するときに、一番悩むことになるのが以下の3点です。
- カスタム投稿タイプには対応しているのか
- どこまで自由にカスタマイズできるのか
- できる場合はどのような手順なのか
実際にテストサイトを作って検証できればよいのですが、既存テーマを使いたい案件はそのような時間もないことがほとんどです。
この「活動記録」を例として、よくあるパターンと、実装までの手順をご紹介します。functions.phpにある程度のPHPを書いたことがある、中級者であれば充分実装できる内容です。
こういうのはアドベントカレンダーに寄稿するものなんですが、年末は恐竜と冒険してました。すみませんすみません。
仕様
WordPressの大きなカスタマイズをするときは「何がしたいか=仕様」をはっきりさせてください。
活動記録は以下のとおりです。
- カスタム投稿タイプ「活動記録」を追加する
- スラッグは「activity」
- 一覧ページ=アーカイブが必要
- 本文は必要ない
- 入力する項目
- タイトル
- 投稿した日(公開日)
- カテゴリー(カスタムタクソノミー)
- リンク先URL
- 詳細ページを作成しない
- 投稿をクリックしたときのリンク先は、リンク先URLにする
- 一覧ページの1ページ目(活動記録のトップ)の上にリード文を表示する
- リード文はウィジェットで管理する
- 表示件数はブログよりも多い30件
このうち、3.の「詳細ページを作成しない」が、Snow Monkeyでは本来想定していない機能で、ちょっとイレギュラーなカスタマイズになります。なので「カスタムフィールドの内容を一覧に表示する」解説を優先して、3.については記事の最後に補足として解説します。
プラグインを作成する
Snow Monkeyのカスタマイズは、テーマに設定されている「フック」を利用してPHPを書くことが多いです。それを書くためのごく簡単なプラグインを作成します。
今回の実装をするための、最低限のファイル構成は以下のとおりです。wp-content/plugins/ 以下にフォルダを作成する前提です。各PHPファイルは、とりあえず空としておいてください。
my-snow-monkey
├ my-snow-monkey.php
├ post_types.php
├ taxonomies.php
├ entry.php
└ widget.php
プラグインのコア「my-snow-monkey.php」については、ここでは割愛します。正式にテーマを購入してアカウントを取得していれば、プラグインのひな形をいつでもダウンロードできますが、WordPressのプラグインの作成はとても簡単なので調べてみてください。
my-snow-monkey.phpは、4つのファイルを呼び出しています。
カスタム投稿タイプを追加する
最初に、カスタム投稿タイプを追加します。プラグインを使用してもいいのですが、変更することはまずないので、私はPHPで書いています。
活動記録を定義している「post_types.php」については、以下のとおりです。作成したいコンテンツに応じて書き換えてください。
mysm_register_post_type_activity
関数は投稿タイプの定義、 mysm_remove_editor_activity
関数は編集画面から本文の入力欄=ブロックエディタを無効にしています。
<?php
/**
* @package my-snow-monkey
* @author YOUR-NAME
* @license none
* @version 1.0.0
*/
function mysm_register_post_type_activity() {
$labels = [
"name" => "活動記録",
"singular_name" => "記録",
"menu_name" => "活動記録",
"all_items" => "すべての記録",
"add_new" => "新規追加",
"add_new_item" => "新規記録の追加",
"edit_item" => "記録の編集",
"new_item" => "新規記録",
"view_item" => "記録を表示",
"view_items" => "記録を表示",
"search_items" => "記録を検索",
"not_found" => "記録が見つかりません",
"not_found_in_trash" => "ゴミ箱内に記録が見つかりません",
"featured_image" => "アイキャッチ画像",
"set_featured_image" => "アイキャッチ画像を設定",
"remove_featured_image" => "アイキャッチ画像を削除",
"use_featured_image" => "記録のアイキャッチ画像として使用",
"archives" => "アーカイブ",
"insert_into_item" => "記録に挿入",
"uploaded_to_this_item" => "この記録へアップロード",
"filter_items_list" => "活動記録を絞り込む",
"items_list_navigation" => "活動記録ナビゲーション",
"items_list" => "活動記録",
"attributes" => "記録の属性",
"name_admin_bar" => "活動記録",
];
$args = [
"label" => "活動記録",
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"has_archive" => true,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"delete_with_user" => false,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => [ "slug" => "activity", "with_front" => true ],
"query_var" => true,
"menu_position" => 6,
"menu_icon" => "dashicons-megaphone",
"supports" => [ "title", "thumbnail", "custom-fields", "revisions", "author" ],
"show_in_graphql" => false,
];
register_post_type( "activity", $args );
}
add_action( 'init', 'mysm_register_post_type_activity' );
function mysm_remove_editor_activity( $use_block_editor, $post ){
if( $post->post_type === 'activity' ){
remove_post_type_support( 'activity', 'editor' );
return false;
}
return $use_block_editor;
}
// add_filter( 'use_block_editor_for_post', 'mysm_remove_editor_activity', 10, 2 );
カスタムタクソノミーを追加する
カスタムタクソノミーを追加します。こちらもプラグインを使用してもいいのですが、PHPで書いています。
カテゴリーを定義している「taxonomies.php」については、以下のとおりです。作成したいコンテンツに応じて書き換えてください。
mysm_register_taxonomy_activity
関数のみですが、重要な設定が一箇所あります。
Snow Monkeyは、設定値の配列の "hierarchical"
(階層)が true
であれば「カテゴリー」、 false
であれば「タグ」として表示します。このため、hierarchicalをfalseにしていると、一覧ページにカテゴリー名を表示することが非常に難しくなります。こだわりがなければtrueにしてください。
<?php
/**
* @package my-snow-monkey
* @author YOUR-NAME
* @license none
* @version 1.0.0
*/
function mysm_register_taxonomy_activity() {
$labels_actcategory = [
"name" => "カテゴリー",
"singular_name" => "カテゴリー",
];
$args_actcategory = [
"label" => "カテゴリー",
"labels" => $labels_actcategory,
"public" => true,
"publicly_queryable" => true,
"hierarchical" => true,
"show_ui" => true,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"query_var" => true,
"rewrite" => [ 'slug' => 'actcategory', 'with_front' => true, ],
"show_admin_column" => true,
"show_in_rest" => true,
"show_tagcloud" => true,
"rest_base" => "actcategory",
"rest_controller_class" => "WP_REST_Terms_Controller",
"show_in_quick_edit" => false,
"show_in_graphql" => false,
];
register_taxonomy( "actcategory", [ "activity" ], $args_actcategory );
}
add_action( 'init', 'mysm_register_taxonomy_activity' );
hierarchicalを変更できない場合
階層構造を変更できない場合は、Snow Monkeyのフックを利用して加工することになります。Qiitaで以前書いた、詳細ページのメタ情報を操作するTIPSを参考にしてください(一覧ページについては未検証です。すみません)。
ウィジェットエリアを作成する
Snow Monkeyでセットされているものとは別の、独自のウィジェット領域=「一覧ページの1ページ目(活動記録のトップ)の上」を追加します。これもPHPで書いています。
ウィジェットを定義している「widget.php」については、以下のとおりです。作成したいコンテンツに応じて書き換えてください。
mysm_widgets_init
関数でウィジェット領域の追加、 mysm_add_activity_widget
関数で、本文の上にウィジェットを表示するよう定義しています。
snow_monkey_prepend_main
はSnow Monkey専用のアクションフックで、本文の上に何らかのHTMLを挿入します。このフックだけでは、すべての画面に挿入されてしまうので「活動記録の一覧ページの1ページ目のとき」という条件分岐を挟んでいます。
!is_paged()
で、1ページ目を判定できます。
<?php
/**
* @package my-snow-monkey
* @author YOUR-NAME
* @license none
* @version 1.0.0
*/
function mysm_widgets_init() {
register_sidebar( array(
'name' => '活動記録: 本文上',
'id' => 'my-widget-activity-main-top',
'before_widget' => '<div id="%1$s" class="c-widget widget_block">',
'after_widget' => '</div>',
) );
}
add_action( 'widgets_init', 'mysm_widgets_init', 10 );
function mysm_add_activity_widget() {
if ( ( is_post_type_archive( 'activity' ) ) && ( !is_paged() ) && ( is_active_sidebar( 'my-widget-activity-main-top' ) ) ) {
echo '<div class="l-archive-top-widget-area" data-is-slim-widget-area="false" data-is-content-widget-area="false">';
dynamic_sidebar( 'ws-widget-activity-main-top' );
echo '</div>';
}
}
add_action( 'snow_monkey_prepend_main', 'mysm_add_activity_widget', 10 );
サンプルコードはGistでも公開しています。
カスタムフィールドを作成する
このコンテンツではカスタムフィールドは「リンク先URL」のひとつだけです。カスタムフィールドに関してはインターフェースのデザインや仕様変更の影響があり難しいので、プラグイン「Advanced Custom Fields」を使用しています。
コンテンツを入力する
表示確認用の活動記録を数件投稿します。カテゴリーも忘れずに。
このコンテンツは各記事を公開した日付を表示するので、公開日が「現在の日付」とは限りません。WordPressの基本の投稿画面だとテキストフィールドで日付を書き換えなければならず、面倒くさいので、カレンダーから公開日を入力できる「Schedule Posts Calendar」プラグインを利用しています。
「外観>ウィジェット」画面で、本文上のリード文を入力します。Snow Monkeyの場合、PHPで追加したウィジェットは「外観>カスタマイズ」画面では入力できないようです。
プラグイン「Snow Monkey Blocks」で、テーマ専用ブロック「メディアとテキスト」を使って書いています。
一覧ページのカスタマイズ
ここまで作業したら、ログインしている状態で、作成した投稿タイプの一覧ページへ移動します。画面の上の横並びの管理バーに「カスタマイズ」があるのでクリックして、投稿タイプ専用のカスタマイズ画面を表示します。
一覧ページを表示している状態でなければ、以下で説明する画面にはならないので注意してください。
「デザイン」をクリックします。
するとこれまではなかった「(投稿タイプ名)アーカイブページ設定」という項目が増えているのでクリックします。
一覧ページの表示の詳細設定画面となります。1カラム・2カラムの変更もここで設定できますが、2カラムだとサイドバーの内容など考慮することが急激に増えるので1カラムが無難です。
「記事一覧レイアウト」の選択肢が重要になります。こだわりがなければ、ブログやトップページの新着で使用していないレイアウトを選んでください。後述の投稿の繰り返し部分のカスタマイズが難しくなります。
ここでは一番シンプルな「テキスト2(text2)」を選択した前提で進めます。
ここまで設定したら「公開」ボタンを押してカスタマイズを終了します。
一覧の表示件数を変更する
ふたたびプラグインの方に戻ります。何も書いていなかった「entry.php」に投稿関係のカスタマイズ用のコードを書いていきます。
一覧を、活動記録だけ30件に増やすカスタマイズは、以下のとおりです。公式のフック pre_get_posts
に「活動記録に関するページ(アーカイブ、カスタムタクソノミー)のときだけ件数を変える」処理を追加します。
function mysm_change_posts_per_page( $query ) {
if( is_admin() || ! $query->is_main_query() ){
return;
}
if( ( get_post_type() === 'activity' ) || ( is_post_type_archive( 'activity' ) ) || ( is_tax( 'actcategory' ) ) ) {
$query->set( 'posts_per_page', 30 );
return;
}
}
add_action(
'pre_get_posts',
'mysm_change_posts_per_page'
);
管理画面の件数を変えてしまわないよう、管理画面であれば処理を中断するようにしています。詳しくは下記のブログを参考にしてください。
カスタムフィールドの内容を一覧に表示する
ウェビングスタジオの「活動記録」では、カスタムフィールドを一覧ページの投稿の繰り返しに表示していません。ですが実際の案件では、カスタムフィールドの値を表示したいケースが多いと思います。
どこに表示するかで、無数のパターンが考えられるので説明が難しいのですが、一番わかりやすいパターンを紹介します。
「メタ情報」の日付やカテゴリーを削除し、カスタムフィールド「test」の値に差し替える
function mysm_render_meta( $html, $name, $vars ) {
if( ( get_post_type() === 'activity' ) || ( is_post_type_archive( 'activity' ) ) ) {
$html = <<< EOL
<div class="c-entry-summary__meta">
<ul class="c-meta">
<li class="c-meta__item c-meta__item--sample">
EOL;
$html .= get_field('test');
$html .= <<< EOL
</li>
</ul>
</div>
EOL;
}
return $html;
}
add_filter(
'snow_monkey_template_part_render_template-parts/loop/entry-summary/meta/meta',
'mysm_render_meta',
10,
3
);
snow_monkey_template_part_render_template-parts/loop/entry-summary/meta/meta
という長い名前のフックが目に入ります。これは「snow_monkey_template_part_render_」よりも後ろがSnow Monkeyのテーマ内のファイルの相対パスになっていて「相対パスで指定したテンプレートの内容を、フックで実行したPHPの出力と入れ替える」という意味になります。
ここでは「template-parts/loop/entry-summary/meta/meta」なので、エントリーの繰り返しのメタ情報となります。
このテンプレートはすべての投稿タイプで共有しているので、このままではブログの記事一覧からカテゴリーが消えてしまいます。このため「活動記録のとき」という条件分岐を追加しています。
サンプルコードはGistでも公開しています。
日付やカテゴリーを残し、カスタムフィールドの値を追加する場合
メタ情報全体を囲んでいる要素、 div.c-entry-summary__meta
の後ろに新しい要素を追加する場合は、先ほどのコードの派生となります。変数 $html
の本来の値に追加をします。
ここでは仮に p.c-entry-summary__test
としました。CSSで見た目を調整してください。
function mysm_render_meta( $html, $name, $vars ) {
if( ( get_post_type() === 'activity' ) || ( is_post_type_archive( 'activity' ) ) ) {
$html .= '<p class="c-entry-summary__test">';
$html .= get_field('test');
$html .= '</p>';
}
return $html;
}
add_filter(
'snow_monkey_template_part_render_template-parts/loop/entry-summary/meta/meta',
'mysm_render_meta',
10,
3
);
最近はCSSで高度なレイアウトができるので、HTMLの親子や順番を気にしなくても良くなりました。なので先ほどの追加で十分対応できると思いますが、何らかの事情で ul.c-meta
内にli要素として挿入しなければならない場合は、ちょっと強引な手段になります。
PHPの正規表現置換を利用するので、バージョンアップの影響を受ける可能性があります。
Qiitaに書いたこちらのTIPSを参考にしてください。
補足:詳細ページを表示しない
解説は以上です。
補足として、活動記録のちょっとイレギュラーなカスタマイズをご紹介します。
ウェビングスタジオの活動記録では、詳細ページへ移動させないようにしています。
Snow Monkeyの投稿一覧は、現時点の仕様では詳細ページへのリンクを削除することができないようです ※。このため、以下のいずれかの対策が必要になります。
- JavaScriptでDOMを操作してリンクを除去する
- 公式フック
the_permalink
でパーマリンクを「#」等に変更し、CSSかJavaScriptでクリックを無効にする
※カスタム投稿タイプの作成時に、 has_archives をfalseにした場合の挙動は確認していません
活動記録では、クリックしたときのリンク先をカスタムフィールドの内容にする必要があったので、後者のカスタマイズをしています。パーマリンクに「/activity/」が含まれていたら書き換えをします。
function mysm_change_permalink( $permalink, $post ) {
if( preg_match( '/\/activity\//', $permalink ) ) {
return get_field('url') ? get_field('url') : '#';
} else {
return $permalink;
}
}
add_action(
'the_permalink',
'mysm_change_permalink',
10,
2
);
Snow Monkeyは、既存テーマを採用しない理由の大半を解決する
自分以外の人が公開しているテーマを、案件で採用しにくい理由として、以下のような事情があります。
- どこまでカスタマイズできるのかわからない
- カスタム投稿タイプは?
- カスタムフィールドは?
- HTMLの操作は?
- バージョンアップしたときに崩れるのが怖い
- いつまでサポートされるのかわからない
- クライアントが自社以外とサブスク契約をすることに難色を示す
最後の「サブスク嫌!」はどうにもならないのですが(ウッキー!)、Snow Monkeyはそれ以外の問題を、高度なカスタマイズ画面、細やかなフィルターフック、豊富なドキュメントの提供などで解決しています。
休日の一日を使って試してみる価値はありますので、ぜひ過去の案件のカスタマイズを試してみてください。
関連記事
- Snow Monkey のカスタマイズは子テーマよりプラグインがオススメ!プラグインの雛形をダウンロードできるようにしました – WordPress テーマ Snow Monkey
- snow_monkey_prepend_main | HAPPY SNOW MONKEY
- snow_monkey_template_part_render | HAPPY SNOW MONKEY
- snow_monkey_entry_meta_items | HAPPY SNOW MONKEY
- Snow Monkeyの「メタ」のカスタマイズについて、いろいろ調べました | ブログ | ウェビングスタジオ
- WordPressテーマ「Snow Monkey」の投稿情報の表示内容を細かく変更する – Qiita