最終更新日:

single.phpで、親カテゴリー→子カテゴリーの順番で表示させる方法

親五平餅くんと子五平餅くん達

こんにちは。五平餅くんです。

WordPressにおける親カテゴリーと子カテゴリーの対応は意外に難しい。

single.phpでの親子カテゴリー表示にはなかなか手こずりました。

今回は、私が手こずった内容について記していきます。

親カテゴリー→子カテゴリーの順番に表示させたい

私が手こずったのは、カテゴリー表示の順番です。

普通にカテゴリー全部を表示させるだけならそこまで難しくはありません。

<ul class="cat-list">
<?php
$categories = get_the_category();
foreach( $categories as $category ) :
?>
  <li class="cat-list__item">
    <a href="<?php echo get_category_link( $category->term_id ); ?>" class="cat-list__link"><?php echo $category->name; ?></a>
  </li>
<?php
endforeach;
?>
</ul>

single.phpで現在のカテゴリーの取得はget_the_category()で行うことができますので、取得後にforeachで現在のカテゴリー一覧を表示しています。

ここでの問題は、子カテゴリーが並列に表示されてしまうという点です。

つまり、全部のカテゴリーを表示するわけですので、親カテゴリーも子カテゴリーも順番がごちゃごちゃになってしまいます。

できれば、このように表示したいわけです!

  • 親カテゴリー1
    • 子カテゴリー1−1
    • 子カテゴリー1−2
  • 親カテゴリー2
    • 子カテゴリー2−1
    • 子カテゴリー2−2

そのためには、このように設定する必要がありそうです。

①一つ目の親カテゴリーを表示する

②一つ目の親カテゴリーに属する子カテゴリーをforeachで表示

③二つ目の親カテゴリーを表示する

④二つ目の親カテゴリーに属する子カテゴリーをforeachで表示

・・・・・・(以下繰り返し)

親カテゴリー→子カテゴリーの順番に表示するコード

結論から述べると下のようにするとできました。

<ul class="cat-list">
<?php

//親カテゴリー
$categories = get_the_category();

foreach( $categories as $category ) :

//親カテゴリーを取得
$parent = $category->parent;

//親カテゴリーがなければ
if( !$parent ) :

?>
  <li class="cat-list__item">
    <a href="<?php echo get_category_link( $category->term_id ); ?>" class="cat-list__link"><?php echo $category->name; ?></a>
    <ul class="cat-list__nest">
    <?php
    //子カテゴリー
    $child_categories = get_the_category();
    foreach( $child_categories as $child_category ) :

    //親カテゴリーを取得
    $parent2 = $child_category->parent;

    //親カテゴリーがある且つ、親カテゴリーが$parentならば
    if( $parent2 && $parent2 == $category->term_id ) :
    ?>
    <li class="cat-list__nest-item">
      <a href="<?php echo get_category_link( $child_category->term_id ); ?>" class="cat-list__nest-link"><?php echo $child_category->name; ?></a>
    </li>
    <?php
    endif;
    endforeach;
    ?>
    </ul>
  </li>
<?php
endif;

endforeach;
?>
</ul>

行われていることは下記3つ。

①親カテゴリーだけをforeachする

②親カテゴリーforeachの中で、属する子カテゴリーを表示する

③この子カテゴリー表示部分を、親カテゴリーの入れ子にする

①親カテゴリーだけをforeachする

<ul class="cat-list">
<?php

//親カテゴリー
$categories = get_the_category();

foreach( $categories as $category ) :

//親カテゴリーを取得
$parent = $category->parent;

//親カテゴリーがなければ
if( !$parent ) :

?>
  <li class="cat-list__item">
    <a href="<?php echo get_category_link( $category->term_id ); ?>" class="cat-list__link"><?php echo $category->name; ?></a>
  </li>
<?php
endif;

endforeach;
?>
</ul>

まず、$categories = get_the_category(); で現在の投稿カテゴリーを全部取得します。

それを、foreachで全部表示していくのですが、ポイントは「親カテゴリーがない場合」を条件とすることです。

下記の部分です。

//親カテゴリーを取得
$parent = $category->parent;

//親カテゴリーがなければ
if( !$parent ) :

endif;

「親カテゴリーがない」カテゴリーということは、一番上の階層にいるカテゴリー、つまり親カテゴリーであるということです。

これで子カテゴリーを表示できなくします。

②親カテゴリーforeachの中で、属する子カテゴリーを表示する

    <ul class="cat-list__nest">
    <?php
    //子カテゴリー
    $child_categories = get_the_category();
    foreach( $child_categories as $child_category ) :

    //親カテゴリーを取得
    $parent2 = $child_category->parent;

    //親カテゴリーがある且つ、親カテゴリーが$parentならば
    if( $parent2 && $parent2 == $category->term_id ) :
    ?>
    <li class="cat-list__nest-item">
      <a href="<?php echo get_category_link( $child_category->term_id ); ?>" class="cat-list__nest-link"><?php echo $child_category->name; ?></a>
    </li>
    <?php
    endif;
    endforeach;
    ?>
    </ul>

今度は親カテゴリーのループの中で子カテゴリーを表示していきます。

まずはお馴染み。$child_categories = get_the_category(); で現在の投稿のカテゴリーを全部取得します。

※この部分は毎回取得する必要がないため、本当はforeachの外に置くのが良いかもしれません。
今回はわかりやすくするためここに置いております。

そして、同じようにforeachで全部表示していきます。ここでポイント!

表示の条件として、親カテゴリーが現在の親カテゴリーである子カテゴリーにしか表示しないようにします。

この部分です。

    //親カテゴリーを取得    
    $parent2 = $child_category->parent;

    //親カテゴリーがある且つ、親カテゴリーが$parentならば
    if( $parent2 && $parent2 == $category->term_id ) :
    
    endif;

$categoryは、最初のforeachで回している親カテゴリーです。

子カテゴリーの親カテゴリーが$categoryと一致すれば表示する条件になっております。

③この子カテゴリー表示部分を、親カテゴリーの入れ子にする

この子カテゴリー表示部分を、親カテゴリーの入れ子にして表示すれば完璧です。

今回の場合だと、「li class=”cat-list__item”」の中に入れてforeachさせます。

一応cssも

一応cssもご紹介します。

/* リセット */
* {
  margin: 0;
  padding: 0;
}

li {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

/* メイン */

.cat-list {
  white-space: nowrap;
  overflow-x: scroll;
  display: flex;
}

.cat-list__item {
  display: flex;
}

.cat-list__item + .cat-list__item {
  margin-left: 15px;
}

.cat-list__link {
  display: inline-block;
  padding: 5px 20px;
  border: 1px solid #333;
  background: #333;
  color: #fff;
  font-size: 14px;
}

.cat-list__link:hover {
  background: #fff;
  color: #333;
  transition: .3s;
}

.cat-list__nest {
  display: flex;
}

.cat-list__nest-item {
  margin-left: -1px;
}

.cat-list__nest-link {
  display: inline-block;
  padding: 5px 20px;
  border: 1px solid #333;
  background: #f2f2f2;
  color: #333;
  font-size: 14px;
}

.cat-list__nest-link:hover {
  background: #ccc;
  transition: .3s;
}

このような表示になります。

親カテゴリー→子カテゴリーの順で表示し、cssを適用

子カテゴリー部分の、線が重なって太くなる問題でmargin-left: -1pxを設定しています。

.cat-list__nest-item {
  margin-left: -1px;
}

これについては以前の記事でも解説しているのでご覧いただけますと幸いです。

borderが重なっているところが太い!!

隣接する要素のborderが重なって太くなる問題

こんにちは。五平餅くんです。 今日は、ブログの投稿一覧ページで、記事と記事が隣接して密着状態のデザインをコーディングしたときにハマったことをお話します。 tableの場合はborderがデフォルトで重なるようになっている tableで表を作りたい時、thとtdにborderをつけたら、border同...

まとめ:親子カテゴリー対応は難しい

よくあるのが一覧ページのサイドバーで、親カテゴリー→子カテゴリーの順番で全カテゴリーを表示するパターンです。

そのパターンならばそこまで難しくありません。

しかし、「現在の投稿のカテゴリー」となるといきなり難しくなりました。一工夫が必要になり、かなりの時間をかけて葛藤することに。。。

これを見ていただいた方が葛藤することのないことを祈っております。

今回は以上です!

最後まで読んでいただきありがとうございました!

(追記)single.php以外でも同じ書き方で対応可能

ちなみに、今回は「single.phpで」という書き方をしましたが、single.php以外でもメインクエリやWP_Queryなどのループ内でも同じ書き方で対応が可能です。

ループ内でget_the_category()を使う場合でしたら、おそらくどのファイルだろうと同じやり方が使えると思います。

また例外が見つかりましたら都度ここに残します!よろしくお願いいたします。

関連記事