アドバイスを求められて「ブログに書いときます」と答えつつ一週間放置した不肖高橋です。元々は「WordPressで特定のカスタムフィールドがついた一覧ページを作りたい」という質問でしたが、同様の質問がよくありそうなので、書いておきます。
例:俺様認定コンテンツの一覧ページを作る
さて、あなたの所属する会社で、WordPressによる社員ブログを運営しているとします。投稿者は社員で、10人ぐらいいます。社長は「これは面白いな」と思った日記を見つけると、カスタムフィールド(キーはauthorized_byで、値は”社長”)をそのコンテンツにつけます。社員達は査定を気にして「どうやったら社長から認定を貰えるか?」ということを考えています。
ここで、社長は「俺が認定したコンテンツだけ一覧表示できるようにしたい」と思います。そんなものが社外の人にとって面白いかどうかはともかく、業務命令なのでやるしかありません。
ステップ1 固定ページを作る
さて、社長認定コンテンツの一覧ページを「社長ふぁぼ」という名前で作ります。スラッグはplesidents-favとしましょう。これに専用のテンプレートを作成して、適用します。
<?php /* * Template Name: 社長ふぁぼ */ ?> <?php get_header(); ?> <ul id="article"> <?php if(have_posts()): while(have_posts()): the_post(); ?> <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li> <?php endwhile; else: ?> <li>社長は何一つ気に入っていません</li> <?php endif; ?> </ul> <?php get_sidebar(); ?> <?php get_footer(); ?>
ステップ2 ループの変更
このままだとthe_titleは「社長ふぁぼ」と出力されるだけです。メインループの中を変えなければいけません。
<?php if(have_posts()): while(have_posts()): the_post(); ?>
上の部分をこのように変えます。
<?php $fav_query = new WP_Query(array( 'post_type' => 'post', 'paged' => get_query_var('paged'), 'meta_key' => 'authorized_by', 'meta_value' => '社長', 'posts_per_page' => get_option('posts_per_page'), 'post_status' => 'publish' )); if($fav_query->have_posts()): while($fav_query->have_posts()): $fav_query->the_post(); ?>
初心者がよくハマるポイントとしては、pagedパラメータを指定せず、常に1ページ目が表示されてしまうところ。get_query_varで現在求められているページを取得します。
そして、endifの後にループをリセットする関数を書いておきます。
<?php endif; wp_reset_query(); ?>
これでループ内はカテゴリーページのようにテンプレートタグが使えます。wp-pagenaviのようなページネーションプラグインもそのまま動きます。
//if(have_posts())内でwp_pagenaviを実行 //先ほど作成したクエリを渡します if(function_exists('wp_pagenavi')) wp_pagenavi(array('query' => $fav_query));
ステップ3 関数化する
この方法の欠点はテーマファイルがごちゃごちゃしてしまうことですので、関数化して別ファイルに書いておくといいかもしれません。
//@functions.php /** * 社長の認定したコンテンツのクエリを返す */ function get_favorites_query(){ return new WP_Query(array( 'post_type' => 'post', 'paged' => get_query_var('paged'), 'meta_key' => 'authorized_by', 'meta_value' => '社長', 'posts_per_page' => get_option('posts_per_page'), 'post_status' => 'publish' )); }
でも、関数化して別ファイルに書いておける人はこの記事をここまで読んでないかもしれません……
以上で一覧ページができました。これで社長に怒られることもなくなります。
追記:数値比較をするには
コメント欄で質問いただいたので、追記しておきます。カスタムフィールドで数値比較もできます。以下のようなケースを想定しましょう。
- カスタムフィールドauthorized_byに入る値は「社長」ではなく、数値である
- authorized_byは整数で、増えたり減ったりする。増やしたり減らしたりするのは10名いる役員。
- 結果的に一つの投稿のカスタムフィールドauthorized_byには0〜10の値が入ることになる
- authorized_byが5以上になると、「役員認定コンテンツ」となる
こうした前提の上で、役員認定コンテンツの一覧を取得します。やることはあまり変わらなくて、上述したget_favrorites_query関数内の配列をちょろっと変えるだけです。
//@functions.php /** * 役員が5人以上認定したコンテンツのクエリを返す */ function get_favorites_query(){ return new WP_Query(array( 'post_type' => 'post', 'paged' => get_query_var('paged'), 'meta_key' => 'authorized_by', 'meta_value' => '5', 'meta_compare' => '>=', //比較演算子を指定 'posts_per_page' => get_option('posts_per_page'), 'post_status' => 'publish', 'order' => 'DESC', //大きい順に並べる 'orderby' => 'meta_value_num' //ソート基準をauthorized_byの数値に )); }
meta_compareというキーを追加することで、meta_valueを絞り込むことができます。使用できる演算子はデフォルトが=で、!=や>=などが使えます。もちろん、大小を比較する場合は数値にしておいた方がよいでしょう。質問は「女の子の胸のカップ数」というものでしたが、AとかBとかで保存するよりは(まあ、アルファベット順なら一応動きますが)、数値に変換した方が無難です。幸い、胸のカップ数は2.5cm刻みなので、Aカップなら100、Bカップなら125とかのmm単位にしておくとよいのではないでしょうか。「AA以下しか見たくない!」という特殊な性癖の持ち主が大量に表れた場合でも対応可能です。
ちなみにソート順を変えたい時は、注意が必要です。カスタムフィールドの値は文字列として保存されているので、orderby => meta_valueとしてしまうと、10の方が2よりも先に来てしまいます。そうした状況を避けるために、orderby => meta_value_numとして、「これは数値だよ」と教えてあげてください。
もっと細かい挙動については、以下の情報を参照してください。
WP_Queryを理解する
さて、上でいきなりnew WP_Queryとか書きましたが、これはWordPressでデータを取得する基本中の基本クラスです。ググるとよくquery_postsが出てきますが、query_postsはWP_Queryの操作を代わりにやってくれている関数です。この記事では「一覧ページ」と説明していますが、テーマ内のどの部分でも使用することができます。
今回は「特定のカスタムフィールドを持った記事の一覧」ということでしたが、他にも色々とできます。new WP_Queryに渡す配列の形式にどんなものがあるのかは、query_postsのページを読んでみてください。WP_Queryのページも見ておくと面白いかも。
おまけ query_postsだけじゃ物足りない
余談です。上で挙げた例としては、「社長の認定」という社外の人間からするとどうでもいい情報のリストですが、他にも色々とアイデアはあるでしょう。一覧ページから辿り着ける情報(個別の投稿)は日付別アーカイブやカテゴリーから辿り着くものと同じなのですが、その「コンテンツの切り分け方」が変わるとこれまで辿り着けなかった人が辿り着けるようになるというわけですね。
[429] [429] Client error: `POST https://webservices.amazon.co.jp/paapi5/getitems` resulted in a `429 Too Many Requests` response: {"__type":"com.amazon.paapi5#TooManyRequestsException","Errors":[{"Code":"TooManyRequests","Message":"The request was de (truncated...)
この「コンテンツの切り分け方」というのは意外と馬鹿にならないもので、Cookpadではまさにこの「コンテンツの切り分け方」が収益源になっており、プレミアムサービスの肝は「人気順にレシピを見られる」ことです。
また、最近リニューアルしたはてなブックマークでも同様のことは行われており、「マイホットエントリー」という機能が追加されました。
ただ、はてな自体はユーザー同士の関係をこれまで重視してこなかった(お気に入りとか全然押してなかった)ためか、ヘビーユーザーで無い限り、パーソナライゼーション(あなたのお友達のオススメ)のデータ元としてTwitterやFacebookのユーザーコネクション情報を使うことになります。結果、TwitterやFacebookのタイムラインとあんま代わり映えしねーなという悲しい事態になっています。だったらわざわざはてブのマイページなんて開かずにはじめからTwitterやうわなにするやめ(ry
というわけで、みんなでコンテンツ作れば母集団が増えて質の高いコンテンツが出てくるというWeb2.0的CGM幻想はもう打ち砕かれており、大量のコンテンツは集まったけど、ほとんどクソでお腹いっぱいという状態をどうやって打破するかということに焦点が集まっています。結局、強いコンテンツって「食い物、かわいいもの(動物/子供/若い女)、健康」とかになっちゃいますからね。みなさんもstudygiftの件で嫌というほど現実を思い知ったことでしょう。
では、WordPressでそういう独自の切り口を導入しようと思うと、いきなり茨の道が眼前に開けてきて、query_postsじゃどうにもならなくなってくるんですね。これに関しては以前書いたので、そっちも参考にしてみてください。この記事の反応がよければwpdbの使い方についても記事を書くかもしれません。以上、もったいぶって終わり。