「おすすめ記事一覧を表示する」を実現する実装方法をあれこれ考えてみた

[WordPressアドベントカレンダー](https://qiita.com/advent-calendar/2021/wordpress)4日目の投稿です。

## これはなに？
「おすすめ記事一覧をTOPに表示する」という、よくある機能をいろんな方法で実装できないかと検討してみた記事になります。
最近WordPressサイトのカスタマイズでおすすめ記事を表示することがあったのですが、どう実装しようかとあれこれ考えたプロセスが楽しかったので、記事にまとめてみました。
これを読んでいる皆さんも自分ならどう実装するかな？と考えながら読んでいいただけたら幸いです。

## 実装するもの
このようなおすすめ記事一覧を実装することとしましょう。（デザインは適当に組んだものです。）
以下の条件を満たしていたら、どんな実装方法でもOKです。

- おすすめ記事が３つ
- TOPページに表示する
- 表示するコンテンツはサムネイル、カテゴリ、タイトル、公開日


![スクリーンショット 2021-12-03 22.11.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94596/93f9e8aa-8ba1-dc3b-4c4b-4c415cfc31cb.png)

## 実装方法をあれこれ考える
それでは「おすすめ記事一覧をTOPに表示する」機能を実装する方法を検討してみましょう

- パターン１：プラグインを利用する
- パターン２：ハードコーディングする
- パターン３：タグを利用する
- パターン４：「Advance Custom Field」と実装の合わせ技
- パターン５：ウィジェットを自前で実装する

ほかにもあると思いますが、この５パターンでそれぞれどのように実装するのか、メリット・デメリットを考えてみましょう。

:::note info
パターン４、５の実装方法の詳細は別の記事にして改めて紹介させていただきます🙇‍♂️
:::

## パターン１：プラグインを利用する
正直これが一番楽ですね
メリットは

- コードを書かなくても実装できる
- 管理画面が用意されるものが多く、運用が楽  

デメリットは

- フルカスタマイズは難しい
- 必要以上の機能が用意されていることがあり、表示速度が遅くなる要因になる

今回は「おすすめ記事一覧をTOPに表示する」という仕様なので、この条件を満たせそうなプラグインを探してきます。
例えば以下のプラグインが候補に上がってくるかと思います。

- [WordPress Popular Posts](https://ja.wordpress.org/plugins/wordpress-popular-posts/)
- [Top 10 – Popular posts plugin for WordPress](https://ja.wordpress.org/plugins/top-10/)
- [WordPress Shortcodes Plugin — Shortcodes Ultimate](https://ja.wordpress.org/plugins/shortcodes-ultimate/)

アクセス数を計測して一覧で表示してくれるプラグインだったり、カテゴリ、タグの条件を指定した記事一覧を表示するショートコードを生成してくれるプラグインになります。
おすすめ記事として表示する条件によって、選択するプラグインは変わってきそうですが、多種多様なプラグインが公開されています。（個々のプラグインの細かい設定方法は省きます。）

## パターン２：ハードコーディングする
HTMLをTOPページに直接記入するだけでも実装可能ですよね

メリットは

- 実装コストが低い

デメリットは

- 更新性が低い

前述したようにおすすめ記事の更新がない場合はこの実装方法を採用することになると思います。もし、「クライアント側で更新したい」、「自動で更新されるようにしたい」などの要望があれば、他の方法を検討しないといけませんね。


### 実装例


``` html
<div class="post-list">
    <div class="post-content">
        <a href="/samle/1111">
            <div class="post-image" style="background-image: url('/wp-content/uploads/2021/12/image01.jpg')"></div>
        </a>
        <div class="post-data">
            <ul class="post-category">
                <li>
                    <a href="/sample"><span>sample</span></a>
                </li>
            </ul>
            <a href="/sample/1111"><h2>Traditional Christmas Market Begins in Strasbourg, France</h2></a>
            <p class="date">2021/12/04</p>
        </div>
    </div>
    <div class="post-content">
        <a href="/sample/2222">
            <div class="post-image" style="background-image: url('/wp-content/uploads/2021/12/image02.jpg')"></div>
        </a>
        <div class="post-data">
            <ul class="post-category">
                <li>
                    <a href="/sample"><span>sample</span></a>
                </li>
            </ul>
            <a href="/sample/2222"><h2>Christmas tree lighting ceremony in the U.S. capital: famous artists present songs</h2></a>
            <p class="date">2021/12/04</p>
        </div>
    </div>
    <div class="post-content">
        <a href="/sample/3333">
            <div class="post-image" style="background-image: url('/wp-content/uploads/2021/12/image03.jpg')"></div>
        </a>
        <div class="post-data">
            <ul class="post-category">
                <li>
                    <a href="/sample"><span>sample</span></a>
                </li>
            </ul>
            <a href="/sample/3333"><h2>10 recommendations for stylish postcards. From Scandinavian designs to cute illustrations</h2></a>
            <p class="date">2021/12/04</p>
        </div>
    </div>
</div>
<style>
    .post-list {
        display: flex;
        align-items: center;
        justify-content: center;
        max-width: 1200px;
        margin: 0 auto;
    }
    .post-content {
        width: calc(100% / 3 - 18px);
        margin: 0 18px 18px 0;
        position: relative;
        height: 360px;
        background: #fff;
    }
    .post-image {
        width: 100%;
        height: 180px;
        background-position: center;
        background-size: cover;
    }
    .post-data {
        padding: 30px;
    }
    .post-category {
        font-size: 12px;
        font-weight: bold;
    }
    .post-data h2 {
        width: 100%;
        height: 72px;
        margin-top: 18px;
        font-size: 18px;
        font-weight: bold;
        line-height: 24px;
    }
    .post-list ul{
        list-style: none;
        margin: 0;
        padding: 0;
    }
    .post-list .date {
        margin-top: 12px;
        color: #7e82a6;
        font-size: 12px;
    }
    .post-list a {
        text-decoration: none;
    }
</style>
```

## パターン３：タグを利用する
おすすめ記事専用のタグを用意して、そのタグが付けられた記事だけを一覧で表示する実装はどうでしょうか？

メリットは

- プラグインなしで実装できる
- 運用が簡単。ダッシュボード内で記事運用ができる

デメリットは

- 拡張性が少し低い
    - 記事の並び順指定はWP_Queryのorderに依存
    - サイト内の記事しか指定できない（外部サイトの記事は指定できない）

### 実装例
おすすめ記事専用のタグを`recommend`として、実装してみます。
記事一覧を取得するには`get_posts()`や`WP Query`がありますが、今回は記事カテゴリも取得したいのでWP Queryを利用します。

get_postsとWP Queryの使い分けについて気になる方はこちらをご覧ください。
https://karukichi-blog.netlify.app/blogs/wp-query-get-posts-difference

``` php
<div class="post-list">
    <?php
        $args = array(
            'tag' => 'recommend',
            'posts_per_page' => 3,
            'orderby' => 'date',
            'order' => 'ASC'
        );
        $query_instance = new WP_Query($args);
    ?>
    <?php if ($query_instance->have_posts()): while ($query_instance->have_posts()): $query_instance->the_post(); ?>
    <div class="post-content">
        <a href="<?= get_the_permalink();?>">
            <div class="post-image" style="background-image: url('<?= get_the_post_thumbnail_url();?>')"></div>
        </a>
        <div class="post-data">
            <ul class="post-category">
                <li>
                    <a href="/sample"><span><?= get_the_category()[0]->name;?></span></a>
                </li>
            </ul>
            <a href="<?= get_the_permalink();?>"><h2><?= get_the_title();?></h2></a>
            <p class="date"><?= get_the_date('Y/m/d');?></p>
        </div>
    </div>
    <?php
        endwhile;
        endif;
        wp_reset_postdata();
    ?>
</div>

```

## パターン４：「Advance Custom Field」と実装の合わせ技
これは自分にとっての「いつものパターン」になります。
[Advance Custom Field](https://ja.wordpress.org/plugins/advanced-custom-fields/)と[Advance Custom Field Repeater](https://www.advancedcustomfields.com/resources/repeater/)を利用するとかなり汎用性の高い実装が可能になります。

メリットは

- 運用が簡単。ダッシュボード内で記事運用ができる
- 外部サイトの記事も追加できる

デメリットは

- 「Advance Custom Field Repeater」は有料アドオン（アドオンがなくても実装は可能だが、あると実装が楽）

### 実装例
実装方法の詳細まで紹介すると記事が長くなってしまいそうなので、詳細は別記事にして紹介させていただきます🙇‍♂️

#### おおまかな流れ
- TOPページ用の固定ページを用意する
- カスタムフィールドからフィールドグループを作成
    - ラベル；recommend_posts
        - フィールドタイプ：繰り返しフィールド
            - ラベル：image
                - フィールドタイプ：画像
            - ラベル：title
                - フィールドタイプ：テキスト
            - ラベル:category
                - フィールドタイプ：テキスト
            - ラベル：published_at
                - フィールド対応：DatePicker
            - ラベル：link
                - フィールドタイプ：テキスト
    - フィールドグループを表示する条件：「ページ」にTOPページ用の固定ページを指定する
- TOPページのカスタムフィールドにデータを入力する
- front-page.phpを作成し、ACFを表示する処理を実装する  

``` php
<div class="post-list">
    <?php if(have_rows('recommend_posts')): ?>
        <?php while(have_rows('recommend_posts')): the_row(); ?>
            <div class="post-content">
                <a href="<?= get_sub_field('link');?>">
                    <div class="post-image" style="background-image: url('<?= get_sub_field('image');?>')"></div>
                </a>
                <div class="post-data">
                    <ul class="post-category">
                        <li>
                            <a href="<?= get_sub_field('category_slug');?>"><span><?= get_category_by_slug(get_sub_field('category_slug'))->name;?></span></a>
                        </li>
                    </ul>
                    <a href="<?= get_sub_field('link');?>"><h2><?= get_sub_field('title');?></h2></a>
                    <p class="date"><?= get_sub_field('published_at');?></p>
                </div>
            </div>
        <?php endwhile; ?>
    <?php endif; ?>
</div>

```

## パターン５：ウィジェットを自前で実装する
少し変化球な気もしますが、ウィジェットを自前で実装する方法もあります。
ウィジェットはサイト中のサイドメニューをカスタマイズする機能かと思われがちですが、WordPressでは自前でウィジェットを実装することでサイドメニュー以外にも利用することができます。

メリットは

- プラグインになしで実装できる
- ダッシュボードの「ウィジェット」から更新できる

デメリットは

- 実装が少し面倒（これまでに紹介した実装例の中で一番書くコード量が多いです）


### 参考例
実装方法を紹介すると記事が長くなってしまいそうなので、詳細は別記事にして紹介させていただきます🙇‍♂️


#### 他にも色々ありそう
ショートコードを実装したり、自前でプラグインを実装したりと他にもやり方はあるかと思いますが、キリがないのでこの辺にしておきます。


## では、どの実装方法を選択する？
いくつか実装方法を挙げさせていただきましたが、リリースする際にはどれか１つを選ばなければいけません。何を基準に実装方法を選べば良いのでしょうか？
基準の１つになるのは、「ユーザやクライアントの要望に応えられるかどうか？」です。
以下にざっと思いつくユーザやクライアントの要望をまとめてみました。

- ユーザビリティ
    - 知りたい情報があること（サイトコンテンツが定期的に更新される）
    - 表示速度  
- 運用コスト  
    - ダッシュボードから更新できる  
    - HTMLなどの知識が必要ない  
- 実装コスト  
    - より少ない工数  
    - 小さく作って効果を確認したい  
    - 機能拡張しやすい
- 他にもたくさん。。。

すべての要望に応える必要はありません。実装する前にヒアリングをして、その要望の中から優先順位を付けて、それらを応えるのに最適な実装方法を選択することになるかと思います。


#### こんな時はどのパターンで実装する？
![hanashiai_business_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94596/cd2fa64f-995c-7ed4-047c-bac96f69790e.png)

##### （クライアント）とりあえずWebで動きだけでみたいです
この場合はパターン２で良いかと思います。
まずは動きを見てもらって、その後の運用に応じて他のパターンに切り替えるのが良さそうです。


##### （クライアント）記事の更新は弊社の担当者で対応したいです
この場合はパターン１、３、４、５に絞り込めますね。
あとはプラグインを追加してOKなのか、タグを任意で追加してOKなのか前提条件を確認して、一番確実な実装手段を選択することになると思います。


## おわり
実装方法を検討し始めるとあれもこれもたくさんやり方はあるな！と想像が広がっていきますよね。自分だったらこう実装するよ！とかアイデアありましたら、コメントいただけると嬉しいです🙋‍♂️