WordPressで構築するサイトで意外と重要なのが、読者に見せる記事一覧(htmlサイトマップ)。ちょっと高度なものを構築するのは大変です。プラグインなしでかつ子カテゴリごとに表示させる方法を示します。
写真1. 多くの列車を一覧できる(尼崎で撮影)
本記事の内容で可能なこと
本記事の内容で可能なことは以下の通りです。
- プラグインなしでhtmlサイトマップを表示すること
- htmlサイトマップを子カテゴリごとに表示すること
- 子カテゴリがある親カテゴリに関しては、親カテゴリ記事一覧を表示しないこと
実例を弊サイトの記事一覧のページをご覧ください。
この実例では
- 子カテゴリのない「サイト運営」については、親カテゴリ直下で記事一覧を表示
- 子カテゴリのある「国内旅行」については、親カテゴリ直下では記事一覧を表示せず、子カテゴリの(例えば)22年GW山口・徳島鉄道旅行の下に記事一覧を表示
- 子カテゴリのある「国内旅行」については、「国内旅行」カテゴリ直下の記事は表示されない
となっています。
弊サイトでは子カテゴリを設定している場合、親カテゴリ直下には記事を設定していません。読者さんの利便性を考えるのであれば、親カテゴリ直下の記事はなくすべきでしょう(子カテゴリに分類できない場合は、「○○カテゴリその他」といった逃げ道を設定し、そこに放りこむのが良いでしょう)。
実装方法
写真2. 複雑なものをまとめねばならない(究極のジャンクション 大和西大寺で撮影)
さて、実装方法を示します。
コードの提示
では、実際のコードを提示いたします(図1)。
- <ul>
- <li><a href="https://tetsudoulab.com/">鉄道ラボトップページ</a></li>
- <?php
- $categories = get_categories('parent=0');
- //ここで親カテゴリを取得した
- foreach($categories as $category){
- echo '<li>';
- echo '<b><a href="';
- echo get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name );
- echo '">';
- echo $category->name;
- echo '</a></b>';
- //次の行で子カテゴリの有無を確認
- $childs = get_categories('child_of='.$category->term_id);
- //子カテゴリがなかった場合の処理を開始
- if(empty($childs)){
- ?>
- <ul>
- <?php
- global $post;$myposts = get_posts('numberposts=100&category=' . $category->term_id);
- foreach($myposts as $post) : setup_postdata($post);
- ?>
- <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
- <?php endforeach; ?>
- </ul>
- <?php
- }
- //子カテゴリがある場合の処理を開始
- else{
- echo '<ul>';
- foreach($childs as $child){
- echo '<li>';
- echo '<a href="';
- echo get_category_link( $child->term_id ). '" title="' . sprintf( __( "View all posts in %s" ), $category->name );
- echo '">';
- echo $child->name;
- echo '</a></li>';
- //ここまで子カテゴリ一覧を表示、ここから当該の子カテゴリに所属する記事を表示
- ?>
- <ul>
- <?php
- global $post;$myposts = get_posts('numberposts=100&category=' . $child->term_id);
- foreach($myposts as $post) : setup_postdata($post);
- ?>
- <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
- <?php endforeach; ?>
- </ul>
- <?php
- }
- echo '</ul>';
- }
- echo '</li>';
- }
- ?>
- </ul>
- <ul>
- <?php wp_list_pages( 'title_li=' ); ?>
- </ul>
図1. 実際のコード
以下の章でコードを解読いたします。
処理の考えかた
コードの細かな規則を解説する前に、どのように処理するのかを示します。
- 親カテゴリを1つ表示する
- 1について、子カテゴリの有無を確認する
- 2において子カテゴリがない場合、当該の親カテゴリの記事を示す
- 2において子カテゴリがある場合、子カテゴリを示す
- 4の子カテゴリに所属する記事を全て示す
- 次の親カテゴリに移り、2~5を繰り返す
親カテゴリ1つ1つに対し、子カテゴリの有無に応じて処理を変えるのがポイントです。
また、最初にホーム画面(トップページ)を示し、最後に固定記事を示しています。これは本項のなかでは大した思考量・作業量ではないので、最後にまとめて記します。
※本記事ではなるべく説明しますが、以下の書籍が手元にあるとより理解しやすいです。
Step1:親カテゴリを取得
まず、親カテゴリを出力します。参考サイト(【WordPress】親カテゴリーと子カテゴリーをul要素の入れ子で一覧表示する方法)によると、
$categories = get_categories('parent=0');
とWordPress関数を使用することにより、最上位カテゴリ(親カテゴリ)のみを出力しています。
<
- foreach($categories as $category){
- echo '<li>';
- echo '<b><a href="';
- echo get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name );
- echo '">';
- echo $category->name;
- echo '</a></b>';
- //子カテゴリの有無を確認
- //子カテゴリの有無に応じて処理
- echo '</li>';
- }
図2. 親カテゴリのタイトルとURLを取得
次に親カテゴリのタイトルとURLを取得します(図2)。ここで配列を繰り返し処理するforeach文は最後に閉じ、閉じる前に次の章で触れる処理を行います。今は親カテゴリ一覧を表示することだけを考え、現段階では、子カテゴリの有無や記事一覧の表示は考えないことにしましょう。
ここでは、親カテゴリの列挙しますので、<li>タグで囲っています。カテゴリ名を出力し、<a>タグでリンクも出力しています。私は親カテゴリを目立たせたいので<b>タグで太字にしましたが、ここは各自の好みで選択すれば良いと思います。
Step2. 子カテゴリの有無を判定
次に子カテゴリの有無を判定します。
- $childs = get_categories('child_of='.$category->term_id);
- if(empty($childs)){
- //子カテゴリのない場合の処理
- }
- else{
- //子カテゴリのある場合の処理
- }
図3. 子カテゴリの有無を判定し、処理を変える
変数を定義し、子カテゴリの有無を確認します(図3)。最初に子カテゴリがなかった場合の処理を行い、次にあった場合の処理を行います。順番は逆でも良さそうですが、記事一覧を先に出力したほうが後が便利そうです(同じ処理を子カテゴリありで行えば良いだけなので)。そのため、子カテゴリなしの場合の処理を先に書きました。
Step3. 親カテゴリ直下の記事一覧を出力
次に、子カテゴリがない場合に親カテゴリ直下の記事を出力します。
- if(empty($childs)){
- ?>
- <ul>
- <?php
- global $post;$myposts = get_posts('numberposts=100&category=' . $category->term_id);
- foreach($myposts as $post) : setup_postdata($post);
- ?>
- <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
- <?php endforeach; ?>
- </ul>
- <?php
- }
図4. 子カテゴリがない場合、記事一覧を出力
listタグを出力するので、ulタグで囲いました。詳細なコードは先人(【WordPress】プラグイン無しでサイトマップを追加する方法。)にならっています。特定のカテゴリに所属する記事のURLと記事タイトルを表示するコードです。
Step4. 子カテゴリがある場合の処理
次に子カテゴリがある場合の処理を挿入します。Step3までで親カテゴリの列挙、当該親カテゴリに所属する記事の列挙といった処理を行いました。今度やりたいことはStep3の内容を親カテゴリから子カテゴリに置き換えるだけです。つまり、基本的にはやることは変わりません。
$childs = get_categories('child_of='.$category->term_id);
と当初に変数を定義していました。この変数を活用します。つまり、$category
という変数を$child
に置き換えるだけです。最初に処理を開始したときのforeach文の内側に入れることに注意しながら、置き換えたコードを付け加えるだけで完了です。
Final step. 固定ページなどを付け加える
最後に固定ページを付け加えます。
- <ul>
- <?php wp_list_pages( 'title_li=' ); ?>
- </ul>
図5. 固定ページを付け加える
固定ページを付け加えます。固定ページにはカテゴリはありませんから、単純なコードです。人によっては投稿記事と固定ページで見出しを付けていることもあると思いますが、読者さんにとっては両者の違いなどどうでも良いものです。そのため、ここでは「固定ページ一覧です」などのような見出しや文言は入れていません。ここは各自の考えによるものでしょう。
また、最初にホームへのリンクも備えています。これも各自の好みだと思います。
HTMLサイトマップを自作してみて
写真3. 親切なイメージ(乗りかえしやすい阪神尼崎で撮影)
PS Auto Sitemapプラグインが7年程度更新されず、安全性に問題があると懸念していました。そのため、プラグインを排除するために今回自作した次第です。
先人の記事を参考に作っていましたが、先人の残してくれた記事には「子カテゴリごとの分類がない」「子カテゴリ直下の記事一覧と親カテゴリに属する記事が重複して表示される(※)」といった問題点がありました。
※弊サイトでいうと、「快速マリンライナーのパノラマグリーンを楽しむ(22年GW、車内と車窓を収録)」という記事が「国内旅行」(親カテゴリ)の一覧と「22年GW山口・徳島鉄道旅行」(子カテゴリ)の一覧で重複して表示されるということです。
今回、子カテゴリがある親カテゴリについて、親カテゴリ直下の記事を表示しないという処理を付け加えることにより、このような重複を解消できたのでした。
同様の記事は多くありますが、内容が深く、かつ親切に書いてある記事がなかったので、今回筆をとってみた(実際はキーボードですが)次第です。
※本記事をより深く理解するには以下の書籍があると良いです!