投稿日:2020年10月5日
本記事はWordPressの投稿一覧ページをPHPを書き換えてカスタマイズする内容となっています。
プログラムを理解している、WordPress中級者くらいの方を対象としています。
WordPressのコアファイルを扱うので、子テーマを作って進めることを強くオススメします。
なお、本記事で紹介した方法で支障が出ても責任は負い兼ねますのでご了承ください。
コロナ禍の影響でWorePress関連の勉強会もオンラインでの開催が推奨されています。
詳しくはこちら
私がよく参加しているのは、
千葉 WordPress Meetup
八王子 WordPress Meetup
WordPressやWebのことを、色々と教えあったりしています。
先日、参加した勉強会でこんな発言がありました。
「数種類あるカテゴリーから、それぞれ1つづつ表示させたい」
というわけで、今回は、WordPressの、複数カテゴリーの投稿記事から1つだけ表示させる方法を検証します。
最初にお見せします。これが結果です。
下図のようにカテゴリーを、カテゴリー01〜カテゴリー10まで、10個作り、それぞれ2、3記事投稿してあります。
▼いつも通りだと、このように表示されます。
▲1ページに表示する最大投稿数は100にしてあります。
各カテゴリーから最新記事が1つ表示されるようにテンプレートを修正していきましょう。
テストサイトのテーマは Lightning を使っています。
▲Plug-In Show Current Template をインストール、有効化すると表示しているページのテンプレートを調べることができるので使ってみてください。
▲ Lightning の投稿ページは front-page.php
を使用しています。
子テーマを作り、front-page.php
を複製して書き換えます。
while ( have_posts() ) :
the_post();
if ( locate_template( $old_file_name, false, $require_once ) ) {
locate_template( $old_file_name, true, $require_once );
} else {
get_template_part( 'template-parts/post/loop', $postType['slug'] );
}
$lightning_loop_item_count++;
do_action( 'lightning_loop_item_after' );
endwhile;
▲元のfront-page.php
89行目付近からのループ文です。
上記の7行目の
get_template_part( 'template-parts/post/loop', $postType['slug'] );
でテンプレートパーツを読み込んで投稿記事を表示させています。
▼このように書き換えました。
// ▼▼▼ get_categories()の初期値。明示的に記載しておく。
$catArrArgs = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
$cats = get_categories($catArrArgs); //カテゴリーを取得
foreach ($cats as $category) { //全てのカテゴリーを取得するループ
$catID = $category->cat_ID; //カテゴリーのID値を取得
$catArgs = array(
'category' => $catID, // ID値で表示
'showposts' => '1', // 1件のみ表示
);
$posts = get_posts($catArgs); //上で設定したID値表示と1件のみの投稿データを取得。投稿データの配列を作成。
if (locate_template($old_file_name, false, $require_once)) { //元からあった記述
locate_template($old_file_name, true, $require_once); //元からあった記述
} else {
if ($posts) {
foreach ($posts as $post) { //投稿を表示するループ
global $post;
setup_postdata($post);
et_template_part('template-parts/post/loop', $postType['slug']); //元からあった記述。ここでテンプレート読み込んでいる。
}
$lightning_loop_item_count++; //元からあった記述
do_action('lightning_loop_item_after'); //元からあった記述
}
}
}
▲元からの記述も残してあります。
補足です。
$catArrArgs = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
▲カテゴリーを取得するget_categories()
パラメータの初期値です。
$catArrArgs
に配列で代入します。
今回、不必要なものもありますが、明示的に記述しておきました。
今回、特に必要なのは 'order' => 'ASC'
です。
ASC
で昇順、 DESC
で降順になります。
パラメータを全て定義しない場合下記のような書き方もできます。
$cats = get_categories(array('order' => 'ASC'));
▲get_categories();
の引数に直接記述します。
foreach ($cats as $category) {
$catID = $category->cat_ID; //カテゴリーのID値を取得
$catArgs = array(
'category' => $catID, // ID値で表示
'showposts' => '1', // 1件のみ表示
);
$posts = get_posts($catArgs);
▲1つ目のループでカテゴリーの数だけカテゴリーID値を取得し $catArgs
にパラメータをセットしています。
'category' => $catID
でID値で取得。
'showposts' => '1'
で1つだけ表示させます。ここを2とかにすると、同じカテゴリーの記事が2つづつ表示されます。
※上記で設定した昇順(ASC)は、2つ以上表示させた各カテゴリーでの並び順となります。
※最終的に表示される全ての順番を並び替えることはできませんでした。
→下記の2021年4月29日 追記でできます。
get_post
の引数として変数 $posts
に代入し投稿データの配列を作成します。
下記のような、まとめた書き方でもOKです。
$posts = get_posts(array('category' => $category->cat_ID, 'showposts' => '1'));
▼残りのソースです。解説はコメントを付与しておきました。
if ($posts) {
foreach ($posts as $post) { //投稿を表示するループ
global $post; //投稿情報をグローバル変数に格納
setup_postdata($post); //投稿情報をグローバル変数に格納
get_template_part('template-parts/post/loop', $postType['slug']); //元からあった記述。ここでテンプレート読み込んでいる。
}
その他、WorePressの関数の詳細はWorePressCodex をご参照ください。
2021年4月29日 追記
The blog of H.Fujimotoさまの記事 を参考にしました。
functions.phpへ下記のソースを追記することで投稿日順にソートすることができます。
function get_cats_and_sort()
{
// 投稿があるカテゴリをすべて読み込む
$cats = get_categories();
// カテゴリの数を得る
$count = count($cats);
// カテゴリの数だけ繰り返す
for ($i = 1; $i <= $count; ++$i) {
// 各カテゴリの最も新しい投稿を読み込む
$where = ['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;
}
▲8行目以外、ソースコードもコメントもそのまま引用させていただいてます。
8行目はfor ($i = 0; $i < $count; ++$i) {
となっていましたが、最新の記事が2つ表示され、最古の記事とその次に古い記事がテレコになってしまいます。
上のようにfor ($i = 1; $i <= $count; ++$i) {
と書くと大丈夫です。
例えば企業ブログをアップする際、とある部署だけの投稿だけになってしまうとか、店舗のお勧め商品をクローズアップして表示したい場合など、カテゴリー分けして活用するといいと思います。
カスタムフィールドを取得し、各カスタムフィールドから任意の数の記事を表示することもできます。
タグやタイトルでも同様なことができるので、必要に応じて使いこなしたいと思います。
上にも書きましたが、表示された全ての記事の投稿順でのソートは頑張りましたけどできませんでした。。。
機会が合ったらチャレンジしたいと思います。
なお、冒頭でも書きましたが、本記事で紹介した方法で支障が出ても責任は負い兼ねますのでご了承ください。
最後まで読んでいただきありがとうございました。