2021.05.22
62

「WordPress Popular Posts」をWP_Queryで使いたい!

wordpressで人気記事などを表示する際に大活躍のプラグイン「WordPress Popular Posts」ですが、テンプレートに組み込む際に融通がきかないというか、なんというか。。。

まずは正攻法

公式に用意されているコードは

<?php
$args = array(
  'post_html' => '<li>{thumb} <a href="{url}">{text_title}</a></li>'
);
wpp_get_mostpopular($args);
?>

こんな感じで、post_htmlのオプションをいじって出力するHTMLを操作するんですよね。
けど、wordpressのWP_Queryを使い慣れてる人からすると、かなり使いにくいというか。微妙に痒いところに手が届かないというか。。。
ちなみにpost_htmlで使える変数は

{thumb} (リンクありで投稿・固定ページのサムネイル画像を表示 (thumbnail_width と thumbnail_height が必要))

{thumb_img} (投稿・固定ページへのリンクなしでサムネイル画像を表示 (thumbnail_width と thumbnail_height が必要))

{thumb_url} (サムネイルの URL を返す (thumbnail_width と thumbnail_height が必要))

{title} (リンクされた投稿・固定ページのタイトルを表示)

{pid} (投稿・固定ページの ID を表示)

{summary} (投稿・固定ページの本文の抜粋を表示 (excerpt_length に0より大きい数が指定されている必要があります))

{stats} (デフォルト統計タグを表示)

{rating} (投稿・固定ページの現在のレートを表示 (WP-PostRatings がインストールされていて有効化されている必要があります))

{score} (投稿・固定ページのレートを数値で表示 (WP-PostRatings がインストールされていて有効化されている必要があります))

{url} (投稿・固定ページの URL を表示)

{text_title} (リンクなしで投稿・固定ページのタイトルを表示)

{title_attr} (similar to text_title, sanitized for use in title/alt attributes)

{author} (投稿者名を返す (stats_author=1 が必要))

{author_copy} (returns linked author name with copy, requires stats_author=1)

{category} (投稿のカテゴリーの返す (stats_category=1 が必要))

{category_copy} (returns linked category name with copy, requires stats_category=1)

{taxonomy} (リンクされたタクソノミー名を返す (stats_taxonomy=1 が必要))

{taxonomy_copy} (returns linked taxonomy names with copy, requires stats_taxonomy=1)

{views} (returns views count only, no text, requires stats_views=1)

{views_copy} (returns views count with copy, requires stats_views=1)

{comments} (コメントカウントのみ (テキストなし) を返す (stats_comments=1 が必要))

{comments_copy} (returns comments count with copy, requires stats_comments=1)

{date} (投稿/固定ページの投稿時間を返す (stats_date=1 が必要))

{date_copy} (returns post/page date with copy, requires stats_date=1)

{total_items} (見つかった人気の投稿数を表示します)

{item_position} (リスト内での投稿の位置を表示します)

と豊富なんですが、個人的にはちょっと使いにくい。。。
フィルターフック「wpp_post」を使えば、やりたいことができるとは思うんですが。。。
もっと使い慣れた形(WP_Query)で使えたらいいなぁ。みたいな感じで今回、いろいろ調べてみました。

結論から言うとプラグインの作者がサポートで答えていたので簡単に実装できました。
この記事にたどり着くまでに時間はかかりましたが。

いらんと思うけど解説

まず、functions.phpに下記コード(簡単に意訳したもの)を書き込みます。

/**
 * Stores views of different time periods as meta keys.
 *
 * @author  @migueleste / @radgh
 * @link    https://wordpress.org/support/topic/how-to-sort-a-custom-query-by-views-all-time-monthly-weekly-or-daily/
 * @param   int     $postid     The ID of the current post/page/custom post type.
 */
function custom_wpp_update_postviews($postid) {
  // Accuracy:
  //   10  = 10回に1回の訪問でビュー数が更新されます。(トラフィックの多いサイトに推奨されます。)
  //   30  = 30%の割合でビュー数が更新されます。(そこそこのトラフィックのサイト向け)
  //   100 = 毎回ビュー数の反映をするよ。リクエストごとにたくさんDBへの書き込み作業が発生するよ。

  $accuracy = 50;

  if ( function_exists('wpp_get_views') && (mt_rand(0,100) < $accuracy) ) {
    // いらんとこ消すか、コメントアウトしてね!
    update_post_meta(
      $postid,
      'views_total',
      wpp_get_views($postid, 'all', false)
    );
    update_post_meta(
      $postid,
      'views_daily',
      wpp_get_views($postid, 'daily', false)
    );
    update_post_meta(
      $postid,
      'views_weekly',
      wpp_get_views($postid, 'weekly', false)
    );
    update_post_meta(
      $postid,
      'views_monthly',
      wpp_get_views($postid, 'monthly', false)
    );
  }
}
add_action('wpp_post_update_views', 'custom_wpp_update_postviews');

このコードの解説を簡単にすると、wpp_post_update_views(ビュー数が更新された)したときにupdate_post_metaでビュー数をそれぞれ対応したカスタムフィールドに上書きしてね。って書いてあります。

例えば、週間ビュー数でソートしたい場合だと、

function custom_wpp_update_postviews($postid) {
  $accuracy = 100;
  if ( function_exists('wpp_get_views') && (mt_rand(0,100) < $accuracy) ) {
    update_post_meta(
      $postid,
      'views_weekly',
      wpp_get_views($postid, 'weekly', false)
    );
  }
}
add_action('wpp_post_update_views', 'custom_wpp_update_postviews');

となるわけですが、
ビュー数が更新されたとき、その投稿のその時のビュー数が「view_weekly」というカスタムフィールドに保存されます。

で、あとはいつも使っているWP_Queryで

$args = array(
  'post_type' => 'post',
  'meta_key' => 'views_weekly',
  'orderby' => 'meta_value_num',
  'order' => 'DESC',
  'posts_per_page' => '3',
);
$top_posts = new WP_Query($args);

と、してやれば簡単にできますよ。
ってことですね。

個人的には

フィルターフック「wpp_post」を使って出力HTMLを変更したり、WPP_Queryを使ったり(今は非推奨)とやり方はいろいろあるし知っておいて損はないと思うけど、今回記事にした方法でやるのが一番簡単で良いかなぁと思います。
あまりトラフィックの多いサイトで$accuracyの値を100とかにしてサーバーに負荷かけないようにだけ注意していただければ。