人気記事プラグイン WordPress Popular Posts のカスタマイズ
主にWP_Query使って表示をがっつりカスタマイズしたいという場合の覚え書き。
【方法1】テンプレートタグを使って表示(簡単だけど複雑なカスタマイズはできない)
テンプレートタグではカテゴリー&タグでフィルターなどの複雑なカスタマイズはできない。
基本の記述
<?php
if ( function_exists( 'wpp_get_mostpopular' ) ) :
$popular_posts = array(
'range' => 'last30days',
'order_by' => 'views',
'post_type' => 'post',
'stats_comments' => '0',
'limit' => 5,
'stats_views' => '0',
'wpp_start' => '<ul>',
'wpp_end' => '</ul>',
'post_html' => '<li><a href="{url}"><img src="{thumb}" alt="{text_title}"><p>{text_title}</p></a></li>',
);
wpp_get_mostpopular( $popular_posts );
endif;
?>
出力をカスタマイズ
基本の記述から ‘post_html’, ‘wpp_start’, ‘wpp_end’ 部分を削除してwpp_custom_htmlフィルターフックでカスタマイズする。
<time>要素はなぜか出力されないので使用しないこと。
function my_custom_popular_posts_html_list( $popular_posts, $instance ) {
$output = '<div id="slider-home-popular" class="post-list --home-topics-popular home-topics-popular__slider">';
foreach ( $popular_posts as $p ) {
$output .= '<article class="post-list__item">';
$output .= '<a href="' . get_permalink( $p->id ) . '">';
if ( has_post_thumbnail( $p->id ) ) {
$thumb_id = get_post_thumbnail_id( $p->id );
$thumb_array = wp_get_attachment_image_src( $thumb_id, 'thumbnail' );
$thumb = '<img src="' . $thumb_array[0] . '" alt="' . $p->title . '">';
} else {
$tags = get_the_tags();
if ( $tags ) {
$thumb = '<img src="' . esc_url( get_template_directory_uri() ) . '/assets/images/common/no-img-' . esc_html( $tags[0]->slug ) . '.png" alt="" width="600" height="3500">';
}
}
$output .= '<div class="post-list__img-wrapper"><figure>' . $thumb . '</figure></div>';
if ( get_field( 'movie', $p->id ) ) {
$output .= '<span class="post-list__movie"><img src="' . esc_url( get_template_directory_uri() ) . '/assets/images/common/icon-movie.svg" alt="動画"></span>';
}
$output .= '<div class="post-list__content"><div class="post-list__timecat">';
$output .= '<span class="post-list__timecat-time">'; //<time>要素が使えない
$output .= get_the_date( 'Y年m月d日', $p->id );
$output .= '</span>';
$output .= '<span class="post-list__timecat-cat">';
$categories = get_the_category( $p->id );
if ( $categories ) {
foreach ( $categories as $c ) {
if ( $c->parent ) {
$output .= esc_html( $c->cat_name );
$output .= ' ';
}
}
}
$output .= '</span></div>';
$ttl = $p->title;
$ttl = mb_strlen( $ttl, 'UTF-8' ) > 20 ? mb_substr( $ttl, 0, 20 ) . '…' : $ttl;
$output .= '<h4 class="post-list__title">' . $ttl . '</h4>';
$output .= '</div>';
$tags = get_the_tags();
if ( $tags ) {
$output .= '<div class="post-list__tags">';
foreach ( $tags as $t ) {
$output .= '<span>';
$output .= $t->name;
$output .= '</span>';
}
$output .= '</div>';
}
$output .= '</a></article>';
}
$output .= '</div>';
return $output;
}
add_filter( 'wpp_custom_html', 'my_custom_popular_posts_html_list', 10, 2 );
//複雑な設定
function my_custom_popular_posts_html_list( $popular_posts, $instance ) {
$output = '';
foreach ( $popular_posts as $p ) {
$output .= '<article>';
$output .= '<a href="' . get_permalink( $p->id ) . '">';
if ( has_post_thumbnail( $p->id ) ) {
$thumb_id = get_post_thumbnail_id( $p->id );
$thumb_array = wp_get_attachment_image_src( $thumb_id, 'thumbnail' );
$thumb = '<img src="' . $thumb_array[0] . '" alt="' . $p->title . '">';
} else {
$thumb = '<img src="' . get_template_directory_uri() . '/assets/images/common/no-img.png" alt="' . $p->title . '">';
}
$output .= '<div class="post-list__img-wrapper"><figure>' . $thumb . '</figure></div>';
// カスタムフィールド
if ( get_field( 'movie', $p->id ) ) {
$output .= '<span class="post-list__osusume"><img src="' . esc_url( get_template_directory_uri() ) . '/assets/images/common/icon-movie.svg" alt="おすすめ"></span>';
}
$output .= '<div class="post-list__content"><div class="post-list__timecat">';
$output .= '<span class="post-list__timecat-time" datetime="';
$output .= get_the_time( 'Y-m-d', $p->id );
$output .= '">';
$output .= get_the_time( 'Y年m月d日', $p->id );
$output .= '</span>';
$output .= '<span class="post-list__timecat-cat">';
$categories = get_the_category( $p->id );
if ( $categories ) {
foreach ( $categories as $c ) {
if ( $c->parent ) {
$output .= esc_html( $c->cat_name );
$output .= ' ';
}
}
}
$output .= '</span></div>';
$ttl = $p->title;
$ttl = mb_strlen( $ttl, 'UTF-8' ) > 31 ? mb_substr( $ttl, 0, 31 ) . '…' : $ttl;
$output .= '<h3 class="post-list__title">' . $ttl . '</h3>';
$output .= '</a></article>';
}
return $output;
}
add_filter( 'wpp_custom_html', 'my_custom_popular_posts_html_list', 10, 2 );
【方法2】new \WordPressPopularPosts\Query を使う
基本
$args = array(
'post_type' => 'post', // 投稿タイプ
'range' => 'monthly', // 集計期間
'limit' => 10, // 表示件数
);
$popular_posts = new \WordPressPopularPosts\Query( $args );
if ( $popular_posts ) :
foreach ( $popular_posts->get_posts() as $popular_post ) :
?>
<a href="<?php the_permalink( $popular_post->id ); ?>">
<?php echo esc_html( get_the_date( 'Y-m-d', $popular_post->id ) ); ?>
<?php echo esc_html( $popular_post->title ); ?>
</a>
<?php
endforeach;
endif;
wp_reset_postdata();
応用
ループ部分をget_template_part()で読み込む場合は set_query_var で変数を渡すなどの工夫が必要
$args = array(
'post_type' => 'post',
'range' => 'monthly',
'limit' => 10
);
$popular_posts = new \WordPressPopularPosts\Query( $args );
if ( $popular_posts ) : ?>
<section>
<h2 class="section__title">アクセスの多いイラスト</h2>
<ul class="post-list">
<?php
foreach ( $popular_posts->get_posts() as $popular_post ) :
set_query_var( 'popular_post_id', $popular_post->id ); //loop-post.phpに渡す変数
get_template_part( 'template-parts/loop', 'post' );
?>
<?php
endforeach;
set_query_var( 'popular_post_id', null ); // !!!【重要】後続のtemplate_partに影響を与えないようにnullに
?>
</ul>
</section>
<?php
endif;
wp_reset_postdata();
loop-post.php
<li class="post-list__item">
<?php
// popular_post_idが定義されていなければnullを返す
$popular_p_id = get_query_var( 'popular_post_id', null );
$popular_p_id = null !== $popular_p_id ? $popular_p_id : get_the_ID();
?>
<a href="<?php the_permalink( $popular_p_id ); ?>">
<div class="post-list__img-wrapper">
<?php if ( has_post_thumbnail( $popular_p_id ) ) : ?>
<?php echo get_the_post_thumbnail( $popular_p_id, 'medium' ); ?>
<?php endif; ?>
</div>
<p class="post-list__title"><?php echo esc_html( get_the_title( $popular_p_id ) ); ?></p>
</a>
</li>
【方法3】WP_Query で扱えるようにする
管理画面からのデータのリセットが効かないのでこれはおすすめしない
公式な使い方では無いかもしれないが、プラグイン作者がSupportで方法伝授してくれている。
wpp_get_viewsの値をカスタムフィールドに保存して、それをWP_Queryの meta_key の値として使用する感じです。
DBへのアクセスは負荷がかかるのでアクセス数の多いサイトなどでは$accuracyの数値は少なく(例えば10)設定するのが良さそうです。
記述例
月刊で取得する場合
functions.php
function custom_wpp_update_postviews($postid) {
// Accuracy:
// 10 = 1 in 10 visits will update view count. (Recommended for high traffic sites.)
// 30 = 30% of visits. (Medium traffic websites.)
// 100 = Every visit. Creates many db write operations every request.
$accuracy = 50;
if ( function_exists('wpp_get_views') && (mt_rand(0,100) < $accuracy) ) {
update_post_meta(
$postid,
'my_views_monthly',
wpp_get_views($postid, 'monthly', false)
);
}
}
add_action('wpp_post_update_views', 'custom_wpp_update_postviews');
テンプレートの表示したい場所に
tax_queryで表示絞り込みする例
$popular_posts = new WP_Query(
array(
'post_type' => 'post',
'meta_key' => 'my_views_monthly', // phpcs:ignore
'orderby' => 'meta_value_num',
'order' => 'DESC',
'posts_per_page' => '3',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => array( 'cathoo' ),
),
array(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => array( 'tagbar' ),
),
),
)
);
if ( $popular_posts->have_posts() ) :
?>
<ul class="xxxxx-list">
<?php
while ( $popular_posts->have_posts() ) :
$popular_posts->the_post();
?>
<?php get_template_part( 'template-parts/loop', 'xxxxx' ); ?>
<?php endwhile; ?>
</ul>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>category/topics/">もっと見る</a>
<?php else : ?>
<p>現在表示する投稿はありません。</p>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
プラグイン作者のフルコード
/**
* 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 = 1 in 10 visits will update view count. (Recommended for high traffic sites.)
// 30 = 30% of visits. (Medium traffic websites.)
// 100 = Every visit. Creates many db write operations every request.
$accuracy = 50;
if ( function_exists('wpp_get_views') && (mt_rand(0,100) < $accuracy) ) {
// Remove or comment out lines that you won't be using!!
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');
// Get the 3 top viewed posts for the week.
$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);
公式ドキュメント
テンプレートタグ
https://github.com/cabrerahector/wordpress-popular-posts/wiki/2.-Template-tags
フィルターフック
https://github.com/cabrerahector/wordpress-popular-posts/wiki/3.-Filters