BLOG

WordPressのカテゴリとタブを動的に表示させる方法

どうも。夏あたりから「クワガタキャラ」として定着したかわゐです。

春夏秋冬、季節を問わずに飼育できるのがクワガタムシ。初めての自己紹介で必ずといっていいほど食いつきがあるのもクワガタムシ。

そして忘年会シーズンの今。話題になると必ずといっていいほど食いつく話題になるのもクワガタムシ。

「カブトムシと何が違うん?」
「年中飼育できるんですか?」
「どのクワガタムシが好きですか?」

このセリフを聞くと、わたしのオタク魂に火が付きます。

そして…

「僕はカマキリが好きなんですよ~」

といった他のジャンルの生き物にも素早く反応します。

そう、メインはクワガタムシですが、カマキリでもサンショウウオでもイリオモテヤマネコでも、かわゐは大丈夫。

生き物が好きな方…とりあえずかわゐと5時間くらい語り合いましょう。

さて、定番の前置きはこれくらいにして、今回はWordPressに関するお話です。

カテゴリーとタブ」を実装するときにかなり詰まってしまいました。

「何や…その実装か(笑)」
「いや、それくらいググれよ」
「なんぼでも記事あるくね?」

と思う方もいるかも知れませんね。

確かに、ググって1ページ目に出てくるような実装であれば、多くの人はきちんと記事を読めば実装できるかと思います。

ですが、そんな簡単に終わるような実装ではありませんでした。

この記事では、もっとかゆいところに手が届くような情報をお伝えします。

それでは、いってみよ~。

WordPressでどんなカテゴリとタブを実装したいのか?

結論から先に申し上げると、「カテゴリーに連動したタブの切り替え」を実装したかったです。

最終的に実装したコードに似せたものが以下のコード。

<div class="categories">
    <ul class="categories_list">
        <li class="categories_list_item click">
            <span>すべて</span>
        </li>
        <?php
            $categories = get_categories($args);
            foreach ( $categories as $category ): 
        ?>
        <?php
            $cat_id = $category->cat_ID;
            $cat_link = get_category_link($cat_id);
        ?>
        <?php if(is_category($cat_id)): ?>
        <li class="categories_list_item check">
            <span><?php echo $category->name; ?></span>
        </li>
        <?php else: ?>
        <li class="categories_list_item">
            <span><?php echo $category->name; ?></span>
        </li>
        <?php
            endif; 
            endforeach;
        ?>
    </ul>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $all_categories = get_posts( array(
                'posts_per_page' => 2,
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $all_categories as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <?php
    $categories = get_categories($args);
    foreach ( $categories as $category ):
    ?>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $comments = get_posts(array(
                'posts_per_page' => 2,
                'category' => $category->cat_ID,
                'orderby' => 'date',
                'order' => 'DESC',
            ));
            foreach( $comments as $post ):
            setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_text"><?php the_content(); ?></p>
                <div class="categories_content_item_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
            <?php
                wp_reset_postdata();
                endforeach;
            ?>
        </div>
    </div>
    <?php
    endforeach;
    ?>
    <a href="<?php echo esc_url( home_url('/category') ); ?>" class="btn">カテゴリ一覧をみる</a>
</div>

クラス、CSS、JavaScript、PHPの変数等については各々で設定していただけたらと思います。

簡単に説明すると、投稿の全記事とカテゴリーの2つで出し分けをし、リスト(categories_list_item click)とコンテンツのカテゴリー部分(categories_content)だけループで回して出力しました。

リスト部分のみのループは、ググればいくらでも出てくるでしょう。

しかし、コンテンツ部分のループというのが全くと言っていいほどでてきません。

気になる方は試しに、「WordPress カテゴリ タブ」とか「PHP カテゴリ 連動」とか「トップページ カテゴリ 出し分け」等で検索してみてください。

マジで出てこんですw

出てはきませんでしたが、それを嘆いても仕方がありません。なので、今までの経験から推測しながら自作しました。

では、検索でよくあるような実装もみていきましょう。

よくあるWordPressでのカテゴリとタブの実装

元々実装していたコード

以下、今回実装する前に実装をしていたコードです。

<div class="categories">
    <ul class="categories_list">
        <li class="categories_list_item click">
            <span>すべて</span>
        </li>
        <li class="categories_list_item">
            <span>カテゴリー01</span>
        </li>
        <li class="categories_list_item">
            <span>カテゴリー02</span>
        </li>
        <li class="categories_list_item">
            <span>カテゴリー03</span>
        </li>
        <li class="categories_list_item">
            <span>カテゴリー04</span>
        </li>
        <li class="categories_list_item">
            <span>カテゴリー05</span>
        </li>
    </ul>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $all_might = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'all_might',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $all_might as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $category01 = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'category01',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $category01 as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $category02 = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'category02',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $category02 as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $category03 = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'category03',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $category03 as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $category04 = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'category04',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $category04 as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <div class="categories_content">
        <div class="categories_content_item">
            <?php
            $category05 = get_posts( array(
                'posts_per_page' => 2,
                'category_name' => 'category05',
                'orderby' => 'date',
                'order' => 'DESC',
            ));
                foreach( $category05 as $post ):
                setup_postdata( $post );
            ?>
            <div class="categories_content_item_block">
                <h3 class="categories_content_item_block_title"><?php the_title(); ?></h3>
                <p class="categories_content_item_block_text"><?php the_content(); ?></p>
                <div class="categories_content_item_block_other">
                    <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d') ?></time>
                    <?php 
                        $category = get_the_category();
                        $cat_name = $category[0]->cat_name;
                    ?>
                    <p class="category"><?php echo $cat_name; ?></p>
                </div>
            </div>
                <?php
                endforeach;
                wp_reset_postdata();
            ?>
        </div>
    </div>
    <a href="<?php echo esc_url( home_url('/category') ); ?>" class="btn">カテゴリ一覧を見る</a>
</div>

クッソ長いですね。笑

ですが、やってることは以下のような記事と変わりません。

(参考)
PHPとjQueryでカテゴリー毎の記事一覧をタブ切り替えするコンテンツの作成

コンテンツの記事数のみをget_posts(); で取得し、foreachのループで出力しています。

あとはリストとコンテンツをJavaScriptで連携させて出し分けました

ググって出てくる実装は、わたしが検索した限りこれが限界…。

では以前の実装の場合は何が不満だったのでしょうか。かわゐ的考察をしてみました。

WordPress側でカテゴリーを追加した時の手間

リストのカテゴリのみループで、他はほぼほぼ静的です。こうなると、WordPressの管理画面から新しくカテゴリーを追加したときに手間がかかります。

実装したサイトを自分だけで使用するのであれば問題ありませんが、クライアントが関わる場合は注意しなければいけません。

クライアントが新しくカテゴリーを追加しても、サイトには反映されませんからね。

そうなると手間ですし、無駄な工賃が発生することになるでしょう。

まぁ、自分だけで使用する場合も、いちいち静的な方に追加しないといけないので、めんどくさいですけどね(笑)

コードが長くなって冗長

これは実装者側の感想なので、使用者に何かあるわけではないです。

この実装に、カテゴリが増えまくったらどうなるでしょうか。

先ほど記載したコードでも、カテゴリが5つしかありません。でも長かったですよね…。

これが10個、20個と増えていったら、めっちゃ長いコードになってしまいます。

冗長なコードはバグの原因にもなりかねません。

負けた気がして悔しい

これは完全にかわゐの主観です。笑

できそうな気がする実装なのに、できないと悔しいです。

今回の実装も、できそうな気がしてできるかできないか…という感じでした。

でも何となく頭には思い浮かんでいたので、実装できるんやろなとは思っていました。

それでできないときが、めっちゃ悔しいんです。

でも今回は実装できたので、かわゐの勝ち。

何で負けたか、明日まで考えといてください。そしたら何かが見えてくるはずです。ほな、いただきます。

【おまけ】JavaScript(Vanilla)でタブの切り替えを実装

動的に出し分ける方法は先ほどまでにご紹介しました。

こちらではおまけとして、タブを切り替えるときの実装を jQuery は使わず、Vanilla JS で記述したコードを記載します。

それがこちら。

  const Category = document.querySelectorAll('.categories_list_item');
  const Contents = document.querySelectorAll('.categories_content');

  for (let i = 0; i < Category.length; i++) {
    Category[i].addEventListener('click', CommentTabToggle);
  }

  function CommentTabToggle() {
    for (let i = 0; i < Category.length; i++) {
      Category[i].classList.remove('click');
    }
    for (let i = 0; i < CommentContents.length; i++) {
      CommentContents[i].classList.remove('appear');
    }

    this.classList.add('click');
    const CategoryTabs = Array.prototype.slice.call(Category);
    const CategoryIndex = CategoryTabs.indexOf(this);
    CommentContents[CategoryIndex].classList.add('appear');
  }

queryselectorAll で取得した値はループを回さないとエラーになるので、for() を使いました。

あとはカテゴリのリストをクリックしたら「click」と「appear」がついたり消えたりするようにしています。

Vanilla JSの場合は、こちらで問題なく動作しました。

が、タブの切り替えは jQuery でも問題なく実装できます。

以前にタブの切り替えで使っていたコードをご紹介しましょう。

$('.tab li').click(function() {
  $('.select').removeClass('select');
  $(this).addClass('select');
  $('.is-show').removeClass('is-show');
  const index = $(this).index();
  $('.content_lists').eq(index).fadeIn(800).addClass('is-show');
  $('.content_lists').not('.is-show').hide();
});

jQueryだと短くてすっきりしていますね。直観的に何が書いているかもわかりやすいです。

リストにクラスを付けたり消したりして、コンテンツにクラスがついてないやつは非表示で!ってことが書かれています。知らんけど。

が、個人的に jQuery は使いたくないので、今は Vanilla に直して使用しています。ライブラリに依存してますからね。

とはいえ、jQueryがなくなることは考えにくいので、どちらを使うかはお任せします。

(Vanilla で記述するクセをつけたら、jQuery がめっちゃ簡単に見えるのでおススメですよ!)

WordPressのカテゴリとタブはこれで決まり!

ということで、WordPressにおけるカテゴリとタブを動的に実装したお話でした。

かわゐが検索した中では、今回実装したものをググってみても、静的なものばかりでした。

自分で使うだけにとどまるなら静的なものでもよいですが、クライアントワークになると話は別です。

無駄に工賃をとってしまうと、信用問題にもつながりかねませんからね。

実装できそうやな~と思ったら、とりあえず挑戦してみましょう!

この記事がかゆいところに手が届くような、そんな記事になっていたら嬉しく思います。

またググってもヒットしないものや、これが欲しかったんや~みたいな実装がでてきたら記事にしていきます。

もし他にも素晴らしい解決法があったら、ご教授ください。それでは!

【参考記事】

テンプレートタグ/get posts – WordPress Codex 日本語版
【サンプルあり】JavaScriptでタブ切り替えを作る
PHPとjQueryでカテゴリー毎の記事一覧をタブ切り替えするコンテンツの作成
タームをタブで表示し所属する記事一覧を表示する方法[WordPress]
WordPressのトップページに任意のカテゴリー毎の一覧を作ろう!

 

WEBデザイナー かわゐ
著者.
WEBデザイナー かわゐ
役職.
WEBデザイナー
資格.
ITパスポート, 世界遺産検定3級

フロントエンドエンジニア歴4年目。「人生は経験だ」と思い、前職は宮古島に就職。しかしクワガタムシがいないのと台風の勢力が化け物過ぎたのとで、大阪へ避難。避難前にリースに応募して入社。入社後はWordPressやECサイトの構築を担当。クワガタに命を捧げるクワガタ系エンジニア。