WordPress Popular PostsにてWPP_Queryクラスを用いて人気記事を出力するあれこれ
WordPressにて人気記事の出力が可能なプラグインと言えばWordPress Popular Posts(※ 以下WPP)が有名だと思います。古くからあるプラグインで、今なおメンテナンスも継続されている事から多くのサイトで使われています。
そんなWPP、バージョン4.0からWPP_Query
クラスが追加されており、このWPP_Queryクラスを用いることでWordPressの投稿requestを取得する標準クラスのwp_query
ライクな使い方が可能になりました。
これまでだとショートコード等を駆使して無理やりwp_queryライクに使えるよう関数を作ったりするのが定番でしたが、今やWPP_Queryのみで簡単に人気記事の投稿を取得出来てしまいます。
というわけで今回はその例のご紹介です。
そもそもWPP_Query
クラスだけで投稿まで取得出来ますが、まずはあくまでもwp_query
ライクに使える様投稿の取得はWordPress標準クラスで取得し、WPP_Queryではwp_queryに渡す引数を取得する例で実装してみます。
/** * Wppからwp_query用args取得. * wppでもwp_queryと同じ感覚で出力できるようidを取得し、wp_queryで用いる形でargsを出力します. * * @param string $post_type カスタム投稿を指定。デフォルトnull. * @param string $range |day|weekly|month|から集計期間を選択. * @param int $limit 取得する件数のリミットを指定. * @return $wpp_id idを返す. */function c_get_wpp_args( $post_type = '', $range = 'weekly', $limit = 5 ) {
$wpp_args = array( 'range' => $range, 'order_by' => 'views', 'post_type' => $post_type, 'limit' => $limit, );
$wpp_query = new WPP_Query( $wpp_args ); $wpp_posts = $wpp_query->get_posts();
$wpp_id = array(); if ( $wpp_posts ) { foreach ( $wpp_posts as $value ) { array_push( $wpp_id, intval( $value->id ) ); } }
$args = array( 'post_type' => $post_type, 'posts_per_page' => $limit, 'orderby' => 'post__in', 'order' => 'DESC', 'post_status' => 'publish', 'post__in' => $wpp_id, 'post__not_in' => get_option( 'sticky_posts' ), );
return $args;}
上記の例のc_get_wpp_args
は以下の引数を持ちます。
- $post_type:投稿タイプ
- $range:期間(day / weekly / month)
- $limit:取得数
$rangeや$limitはWPP_Query
特有の引数ですね。1日毎のランキングを取得したい場合はday
、一週間単位ならweekly
といった感じで指定していきます。
肝になるのは以下の部分です。一旦WPP_Query
クラスで投稿を取得し、foreachでループを回していますがその際に投稿idを配列に入れていきます。
$wpp_query = new WPP_Query( $wpp_args );$wpp_posts = $wpp_query->get_posts();
$wpp_id = array();if ( $wpp_posts ) { foreach ( $wpp_posts as $value ) { array_push( $wpp_id, intval( $value->id ) ); }}
// array_mapを使うならこんな感じもあり.$wpp_id = array_map( function( $wppost ) { return (int)$wppost->id; }, $wpp_query->get_posts());
投稿idの配列はその下の$argsのpost__in
で使用しています。こうすることでWPP_Query
にて取得した投稿と同じ投稿を取得出来るwp_query
用の引数が出来上がります。
あとはこれを通常通りループを回してしまえばwp_query
ライクな使い方が出来るというわけです。
<?php$query = new WP_Query( c_get_wpp_args( 'blog', 'weekly', 3 ) );
if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); get_template_part( 'template/item-blog' ); }} else { get_template_part( 'inc/parts-nopost' );}wp_reset_postdata();?>
上記方法のメリットはget_template_part
で読み込むテンプレートの中身を通常ループと同じ内容で利用できるという点です。
通常のループでも、WPPの投稿を取得するループでも全く同じテンプレートを読み込むことが出来るのが1番のメリットと言っていいでしょう。
一方デメリットとしてはWPP_Query
とwp_query
の2回クエリを発行している点です。無駄と言えば完全に無駄です。
というのも前述した通りWPP_Queryだけでも投稿の取得は勿論可能で、以下の様にすることでループを回すことが出来ます。
$wpp_args = array('range' => $range,'order_by' => 'views','post_type' => $post_type,'limit' => $limit,);
$wpp_query = new WPP_Query( $wpp_args );$wpp_posts = $wpp_query->get_posts();
if ( $wpp_posts ) { foreach ( $wpp_posts as $wpp_post ) {
$post_id = $wpp_post -> id; // 投稿ID get_template_part( 'template/item-blog' );
}}
ただ$wpp_post -> id
といった様に通常のループwp_query
で取得できる形と異なってしまう為、読み込むテンプレート内でのidの取得等は$post->ID
ではなく、別途変数を用意するなりしてWPPの時でもidが取得できる様に工夫する必要がありそうです。
一旦idだけ取得してその後wp_query
で取得するのか、それともWPP_Query
だけでスマートに投稿を取得するのか、用途に合わせた実装を選んでみて下さい。