「WordPressで学ぶPHP(3)関数編」を発売しました。
本書は「WordPressで学ぶPHP(1)変数・制御構造編」「WordPressで学ぶPHP(2)データ構造(配列・オブジェクト)編」の続編にあたり、PHP組み込みの関数や、独自の関数を作る方法などを解説します。
Kindle本で、定価400円です。
WPでカテゴリを投稿の新しい順に並べ替える
昨日、Facebookで以下のような質問を見かけました。
Wordpress、というかプログラミングに長けたお優しい方、たすけてー!
・カテゴリごとの「一番古い記事」の情報だけを表示したい
・新しく更新されたカテゴリ順に表示したい
場合、どうすればいいのでしょうか...
この質問に答えます。
1.具体的な出力の例
カテゴリと投稿が、以下のような構成であるとします。(各カテゴリの一番上にある投稿が最も新しく、一番下にある投稿が古い)。
この場合、投稿を「b2 c3 a3」の順に出力したいとのことです。
Aカテゴリ ┣ a1(更新日:2日前) ┣ a2 ┗ a3 Bカテゴリ ┣ b1(更新日:今日) ┗ b2 Cカテゴリ ┣ c1(更新日:1日前) ┣ c2 ┗ c3
2.考え方
質問の事例は、以下のようにして出力することができます。
2-1.カテゴリの読み込み
まず、WordPressのget_categories関数を使って、投稿があるカテゴリをすべて読み込みます。
2-2.各カテゴリの最も新しい投稿/最も古い投稿を読み込む
次に、WordPressのget_posts関数を使って、各カテゴリの最も新しい投稿と、最も古い投稿を読み込みます。
最も新しい投稿は、カテゴリを並べ替えるために使います。
一方、最も古い投稿は、出力したい情報です。
2-3.カテゴリを並べ替える
次に、カテゴリを、それぞれのカテゴリの最も新しい投稿の順に並べ替えます。
並べ替え方法がやや複雑なので、PHPのusort関数を使って、順序の判断方法を関数で指定するようにします。
2-4.結果を出力する
2-1~2-3で得られた結果をもとに、並べ替え後の各カテゴリの最も古い投稿を出力します。
3.functions.phpに処理を追加
2-1~2-4のうち、2-1~2-3でロジックだけで出力を伴わない部分です。
ロジックの部分をindex.php等のテンプレートに長々と書くと、HTMLとPHPが混在してコードが読みにくくなります。
このように、ロジックのみの部分は、functions.phpに関数として記述し、ロジック(PHP)とHTMLを極力分離することをお勧めします。
今回の例では、以下のコードをfunctions.phpに追加します。
function get_cats_and_sort() { // 投稿があるカテゴリをすべて読み込む $cats = get_categories(); // カテゴリの数を得る $count = count($cats); // カテゴリの数だけ繰り返す for ($i = 0; $i < $count; $i++) { // 各カテゴリの最も新しい投稿を読み込む $where = array('category' => $cats[$i]->term_id, 'orderby' => 'post_date', 'order' => 'desc', 'numberposts' => 1); $newest_posts = get_posts($where); // カテゴリのオブジェクトに「newest_post」というメンバを追加して、最新の投稿を代入する $cats[$i]->newest_post = $newest_posts[0]; // 各カテゴリの最も古い投稿を読み込む $where['order'] = 'asc'; $oldest_posts = get_posts($where); // カテゴリのオブジェクトに「olddest_post」というメンバを追加して、最新の投稿を代入する $cats[$i]->oldest_post = $oldest_posts[0]; } // カテゴリを、最新の投稿の日付が新しい順に並べ替える usort($cats, 'sort_by_postdate'); // 結果を返す return $cats; } function sort_by_postdate($a, $b) { // 2つのカテゴリの最新の投稿(newest_postメンバ)の日付の大小関係を返す return ($a->newest_post->post_date == $b->newest_post->post_date) ? 0 : ($a->newest_post->post_date < $b->newest_post->post_date) ? 1 : -1; }
各カテゴリの最も古い/新しい投稿を読み込み、カテゴリのオブジェクトのメンバにします(7~18行目)。
そして、usort関数を使って、最も新しい投稿の日付の降順に並べ替えます(20行目)。
usort関数では、並び順を判断するために、sort_by_postdate関数を呼び出すようにします(25~29行目)。
この関数では、各カテゴリの最新の投稿(newestメンバ)の日付(post_dateメンバ)で、カテゴリの大小を判断します。
4.テンプレートの書き換え
次に、index.php等、情報を出力したいテンプレートを書き換え、以下の部分を追加します。
<?php // カテゴリと各カテゴリの最も古い投稿を読み込む $cats = get_cats_and_sort(); // カテゴリの数を得る $count = count($cats); // カテゴリの数だけ繰り返す for ($i = 0; $i < $count; $i++) : ?> <?php // 最初のカテゴリの前に<ul>タグを出力する ?> <?php if ($i == 0) : ?><ul><?php endif; ?> <li> <?php // カテゴリの最も新しい投稿の情報を出力できるように準備する ?> <?php $post = $cats[$i]->newest_post; setup_postdata($post); ?> <?php // カテゴリ名を出力し、カテゴリアーカイブページにリンクする ?> <a href="<?php echo get_category_link($cats[$i]->term_id); ?>"><?php echo $cats[$i]->name ?></a> <?php // カテゴリの最も新しい投稿の日付を出力する ?> (<?php echo get_the_date(); ?>)<br /> <?php // カテゴリの最も古い投稿の情報を出力できるように準備する ?> <?php $post = $cats[$i]->oldest_post; setup_postdata($post); ?> <?php // 投稿のタイトルを出力し、投稿のページにリンクして、投稿の日付も出力する ?> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>(<?php echo get_the_date(); ?>) </li> <?php // 最後のカテゴリの後に</ul>タグを出力する ?> <?php if ($i == $count - 1) : ?></ul><?php endif; ?> <?php endfor; ?>
手順3で定義したget_cats_and_sort関数を使って、並べ替え後のカテゴリを読み込みます(3行目)。
そして、それらのカテゴリを順に繰り返し(7行目)、各カテゴリの情報と(12~17行目)、カテゴリの最も古い投稿の情報を出力します(18~21行目)。
なお、上のリストでは、カテゴリと投稿の関係が分かるように、カテゴリの情報も出力しています。
しかし、元の質問では、投稿の情報だけを出力すれば良いようです。
その場合、カテゴリの情報を出力する部分(12~17行目)を削除します。
5.MTならどうする?
以前に、Movable Typeで同様の質問を受けて、記事を書いたことがあります。
Movable Typeユーザーの方は、以下の記事をご参照ください。
また、現在開発中のWPConnectorプラグインを使うと、WordPressの情報を、Movable Typeのテンプレートで出力することができます。
今回の質問のようなことも、Movable Typeのテンプレートで書くことができます。
その方法は後日解説します。
なお、WPConnectorプラグインについては、6月29日(土)に開催する「MTCafe Saitama 2013」で紹介します。
ご興味がある方はぜひお越しください。