鳥山(@sysbird)です、
WordPress Advent Calendar 2013 6日目のブログになります。Adventとは、キリスト降誕を待ち望む期間のことという。その期間、お菓子が隠された小窓を毎日ひとつづつ開けて楽しむのがAdvent Calendarだ。(昨年よりコピペ)
お菓子にちなみ本日は、私が運営しているブログ「お菓子の虜」にてカスタム投稿タイプを使って国内お菓子メーカーを登録した事例を紹介したい。「お菓子の虜」とはコンビニで買って食べたお菓子を記録するブログだ。いままでに食べたお菓子は2271種類となる。
お菓子メーカーの一覧を作りたい
「お菓子の虜」では、投稿記事となるお菓子に対してお菓子メーカーをカスタムフィールドで入力している。それを10年以上続けていながら、メーカーはある程度決まっているのだから一覧から選択できる方法はないものか?と思っていた。
そんなおりに出会ったのが、遅ればせながらカスタム投稿タイプである。
カスタム投稿タイプを登録する。
まずはお菓子メーカーの一覧をカスタム投稿タイプで作ってみよう。カスタム投稿タイプを利用するは、functions.phpに以下のように記述する。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function my_custom_post_type() { $labels = array( 'name' => 'お菓子メーカー', 'all_items' => 'お菓子メーカーの一覧' ); $args = array( 'labels' => $labels, 'public' => true, /* 公開するかどうが */ 'show_ui' => true, /* メニューに表示するかどうか */ 'menu_position' => 5, /* メニューの表示位置 */ 'has_archive' => true, /* アーカイブページの作成 */ 'supports' => array( 'title', 'custom-fields' ) ); register_post_type( 'maker', $args ); } add_action( 'init', 'my_custom_post_type', 0 ); |
register_post_type()のパラメータsupportsではカスタム投稿タイプでどんな入力項目を使うか指定する。タイトルや本文、アイキャッチなど通常の投稿に用意されているのを同じ入力項目から選ぶことができる。お菓子メーカーでは本文は必要ないので、投稿タイトルとカスタムフィールドのみとした。
するとダッシュボードには「お菓子メーカー」の項目が表示される。
この段階で投稿画面はタイトルのみ。
カスタム投稿でカスタムフィールドを使う
カスタム投稿タイプを登録する際にcustom-fieldsを指定したので、カスタムフィールドを利用して「ふりがな」「URL」を入力するとしよう。
カスタム投稿でカスタムフィールドを使うにはプラグインAdvanced Custom Fields(AFC)がお手軽だ。インストール、有効化したら設定画面にて「お菓子メーカー」というフィールドグループを追加し、ふりがなとURLのフィールドを追加する。
ルールとして投稿タイプがmakerに等しいとなるように指定する。このフィールドグループがお菓子メーカーの登録画面のみ表示されるようにするためだ。
お菓子メーカーの登録画面では、タイトルのほかにふりがなとURLを入力できるようになる。
お菓子メーカーを延々登録していく。
投稿画面でお菓子メーカーを参照する
お菓子メーカーの一覧ができたならば、あとは毎日食べるお菓子(投稿)にどのようにひもづけてゆくかである。投稿と投稿の関連付けを行うプラグインとして、以下3つが挙がった。
Custom Post Types Relationships
導入が簡単
関連付け候補の投稿タイプを指定することができない
カスタムフィールドに保存される(シリアライズ化)
導入が面倒(functions.phpの編集が必要)
関連付け候補の投稿タイプを指定することができる
独自のテーブルに保存される
導入が簡単
関連付け候補の投稿タイプを指定することができる
候補の検索UIがよい
カスタムフィールドに保存される(シリアライズ化)
独自のテーブルに保存されるのは避けたい。かといってカスタムフィールドの値がシリアライズされるのもよくないと思いつつAdvanced Custom Fieldsを選んだ。投稿画面での検索UIがよく、関連付け候補の投稿タイプを限定できるのがポイントだった。
Advanced Custom Fieldsでお菓子メーカーを関連付ける
Advanced Custom Fields(AFC)は先ほどお菓子メーカーを登録する際にも利用した。ここでは投稿画面のために「お菓子情報」というフィールドグループを追加し、価格とメーカーのフィールドを追加する。
フィールドタイプのルールとして投稿タイプがpostに等しいとなるように選択する。このフィールドグループが通常の投稿画面のみ表示されるようにするためだ。
メーカーのフィールドタイプは関連とし、関連づける投稿タイプをmakerにしておく。
こうすることで、投稿画面でお菓子メーカーを選択する際にmakerの一覧より検索できるようになる。
ブログ上でお菓子メーカーを表示するには?
ブログ上でお菓子メーカーを表示してみよう。
ACFでは、設定したカスタムフィールドの値を取得するための関数get_field()が用意されている。トップページ(index.php)や詳細ページ(single.php)でお菓子メーカーを表示するには以下のようになる。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php $my_posts = get_field( 'maker', $ID ); if( $my_posts && is_array( $my_posts )): foreach( $my_posts as $p ): ?> <a href="<?php echo get_permalink($p->ID); ?>"> <?php echo get_the_title($p->ID); ?></a> <php endforeach; wp_reset_postdata(); endif; ?> |
お菓子メーカーの一覧を表示する
カスタム投稿タイプmakerの投稿一覧は、ブログURL/maker/
というパーマリンクとなる。テンプレートはarchive.phpだ。
ページタイトル
カスタム投稿タイプの一覧のページタイトルは、条件分岐で通常のアーカイブページと区別する必要がある。
1 2 3 4 5 6 7 8 |
<h1> <?php if ( is_post_type_archive() ) : /* カスタム投稿タイプのアーカイブ */ ?> <?php $post_type = get_post_type_object( get_query_var( 'post_type' ) ); ?> <?php echo $post_type->label; ?> <?php elseif( is_category() ) : /* カテゴリーのアーカイブ */ ?> 「<?php echo single_cat_title( '', false ); ?>」に関するお菓子 <?php endif; ?> </h1> |
カスタム投稿タイプの一覧
投稿一覧を表示する場合も、カスタム投稿タイプと投稿では持つデータが異なる場合があるので区別したほうがよいだろう。
例えば、
・カスタム投稿タイプの一覧 → 記事タイトル(メーカー名)とふりがなを表示
・それ以外のアーカイブ → 記事タイトル(お菓子名)とメーカー名を表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<ul> <?php while ( have_posts() ) : the_post(); ?> <li> <a href="<?php the_permalink() ?>" rel="bookmark"><span><?php the_title(); ?></span> <?php if ( is_post_type_archive() ) : /* カスタム投稿タイプのアーカイブ */ ?> <em> <?php echo get_field( 'furigana', $ID ); /* お菓子メーカーのふりがなを表示 */ ?> </em> <?php elseif( is_archive() ) : /* その他のアーカイブ */ ?> <?php /* お菓子メーカーを表示 */ $my_posts = get_field( 'maker', $ID ); if( $my_posts && is_array( $my_posts ) ): foreach( $my_posts as $p ) : ?> <em><?php echo get_the_title( $p ); ?></em> <?php endforeach; endif; ?> <?php endif; ?> </a> </li> <?php endwhile; ?> </ul> |
お菓子メーカーの詳細ページを表示する
お菓子メーカーの詳細ページに、そのお菓子メーカーが販売しているお菓子の一覧を表示してみよう。
カスタム投稿タイプmakerの詳細ページは、single-maker.phpというテンプレートを用意すればよい。
ここで、現在の投稿ID(お菓子メーカーのID)に関連する投稿一覧を取得し表示する。お菓子とお菓子メーカーはACFによってカスタムフィールドにて関連付けられている。つまり、現在の投稿IDをカスタムフィールドに持つ投稿(お菓子)を検索するのだ。カスタムフィールドで検索を行うには、get_posts()のパラメータmeta_queryにオプションを指定することで可能だ。
ここまでは計画どおりだったのに問題が!
ACFではカスタムフィールドがシリアライズ化されているため、meta_queryでの検索がうまくできない。このような場合はカスタムフィールドの検索オプションとしてLIKEが使えると知った。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<h1>「<?php the_title(); ?>」のお菓子</h1> <ul> <?php /* 検索パラメータを設定 */ $param = array( 'showposts' => -1, 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'maker', 'value' => $post->ID, 'compare' => 'LIKE' ) ) ); /* WordPressのループ処理 */ $myposts = get_posts( $param ); foreach( $myposts as $post ){ setup_postdata( $post ); /* 1件の投稿 */ ?> <li><a href="<?php the_permalink() ?>"><?php the_title() ?></a></li> <?php } ?> </ul> |
どうにかお菓子メーカーごとのお菓子一覧を表示することができた
meta_queryのオプションにLIKEを使うということは「カスタムフィールドにお菓子メーカーの投稿IDが含まれる場合」という条件になる。どうにもあやふやな検索だ。そもそもWordPress上、カスタムフィールドで検索を行うことが向いていないとの意見もある。
課題
勢いで実践したものの課題が残る。
・投稿とカスタム投稿タイプを関連づけるのに最適な方法はあるのか?
・候補として挙がったプラグインよりもおすすめプラグインはあるか?
・この場合は自分で作ったほうがよいのか?
・カスタム投稿タイプの使い方が適していないのか?
・検索対象とするならば、お菓子メーカーはどのようなデータに持つべきか?
突っ込みやアドバイスお待ちしています。
WordPress Advent Calendar 2013 明日はわたさんの登場です、お楽しみに!
[…] 初めまして! WordPress Advent Calendar 2013 6日目担当の木谷(@kimipooh)です。 今年初めての参加です。 本日は、私以外に鳥山さん(@sysbird)もご担当ですね。はやい….もうアップされてる…。しかも綺麗で纏まったデザインですよねぇ。そこはマネできない部分なので、マイペースで行きたいと思います! また本サイトのデザイン・レイアウトは全くカスタマイズしてません。というか個人サイトぐらいは管理運用から離れたいので、もういいや!みたいな感じです…そのため多少見づらいかもしれません、そのあたりはご容赦を… […]
仕事のサイト(http://www.tuj.ac.jp/icas/)ではposts2postsを使っていますが、その時に下記2つも検討しました。Typesは結構よい感じだったんですが、かゆいところに手が届くには有料版が必要で。。。て感じで、Podsは機能盛りだくさんで複雑そうだったのでやめました。
WordPress › Types – Custom Fields and Custom Post Types Management « WordPress Pluginshttp://wordpress.org/plugins/types/
WordPress › Pods – Custom Content Types and Fields « WordPress Pluginshttp://wordpress.org/plugins/pods/
>Toruさん、
ありがとうございます!お菓子メーカーに関してはこれで完成とせずに、いろいろ試していきたいです
[…] カスタム投稿タイプでお菓子メーカーを登録して今日食べたお菓子にひもづけるには? […]