ニケッチャニッキ

はてなブログ・WordPressカスタマイズ・Androidプログラミング

WordPressプラグインなしで人気記事リストを表示する方法2パターン

f:id:niketcha:20190711151303p:plain

WordPressのプラグインを使わずに人気記事リストを表示する方法を検索すると、たくさん出てきてしまって迷うと思います。

そこで私が試してみていいなと思った方法を2つ紹介します。

手軽に実装したい方に

manablogさんの方法を参考にさせていただきました。

コードが短くシンプルなので、簡単な方法を探している方向けです。

function.phpに追加するコード

// 人気記事出力用
function getPostViews($postID){
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
        return "0 View";
    }
    return $count.' Views';
}
function setPostViews($postID) {
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        $count = 0;
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
    }else{
        $count++;
        update_post_meta($postID, $count_key, $count);
    }
}
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);

人気記事を表示する場所に追加するコード

<?php
// views post metaで記事のPV情報を取得する
setPostViews(get_the_ID());

// ループ開始
query_posts('meta_key=post_views_count&orderby=meta_value_num&posts_per_page=5&order=DESC'); while(have_posts()) : the_post(); ?>

<dl class="popularlist">
    <dt>
        <!-- サムネイルの表示 -->
        <a href="<?php echo get_permalink(); ?>"><?php the_post_thumbnail( 'thumbnail' ); ?></a>
    </dt>
    <dd>
        <!-- タイトルの表示 -->
        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    </dd>
</dl>
<?php endwhile; ?>

こちらはご自身のページに合わせて適宜修正してください。

私の使ってるSTINGER8の最新記事リストがdlタグを使った構成になっていたので、人気記事もその形を踏襲しました。divでもulでもできます。

もっと正確なアクセスランキングを表示したい方に

私は今こちらの方法を採用しています。

行き着く先はあんこさんの方法を参考にさせていただきました。

ボットのアクセスや管理者のアクセスを除外していることと、ランキング集計期間が24時間になっているのが特徴です。

集計期間を設けないと過去記事が有利になってしまうので、新しい記事も同様に扱いたい人向け。

function.phpに追加するコード

//アクセス数をカウントする
function set_post_views() {
    $postID = get_the_ID();
    $num = (int)date_i18n('H'); // 現在時間で番号取得
    $key = 'pv_count';
    $count_key = '_pv_count';
    $count_array = get_post_meta( $postID, $count_key, true );
    $sum_count = get_post_meta( $postID, $key, true );
    if( !is_array($count_array) ) { //配列ではない
        $count_array = array();
        $count_array[$num] = 1;
    } else { //配列である
        if ( isset( $count_array[$num] ) ) { //カウント配列[n]が存在する
            $count_array[$num] += 1;
        } else { //カウント配列[n]が存在しない
            $count_array[$num] = 1;
        }
    }
    //アクセス数を更新する
    update_post_meta( $postID, $count_key, $count_array );
    update_post_meta( $postID, $key, $sum_count + 1 );
}

//アクセス数をリセットする
function reset_post_views() {
    $num = (int)date_i18n('H');
    $key = 'pv_count';
    $reset_key = '_pv_count';
    $args = array(
        'posts_per_page'   => -1,
        'post_type' => 'post',
        'post_status'=>'publish',
        'meta_key' => $reset_key,
    );
    $reset_posts = get_posts($args);
    if($reset_posts):
        foreach($reset_posts as $reset_post):
            $postID = $reset_post->ID;
            $count_array = get_post_meta( $postID , $reset_key, true );
            if ( isset( $count_array[$num] ) ) { //カウント配列[n]が存在する
                $count_array[$num] = 0;
            }
            //アクセス数をリセットする
            update_post_meta( $postID, $reset_key, $count_array );
            update_post_meta( $postID, $key, array_sum( $count_array ) );
        endforeach;
    endif;
}

//リセット関数を実行するアクションフックを追加
add_action( 'set_hours_event', 'reset_post_views' );

//実行間隔の追加
function my_interval( $schedules ) {
    // 1時間ごとを追加
    $schedules['1hours'] = array(
        'interval' => 3600,
        'display' => 'every 1 hours'
    );
    return $schedules;
}
add_filter( 'cron_schedules', 'my_interval' );

//アクションフックを定期的に実行するスケジュールイベントの追加
function my_activation() {
    if ( ! wp_next_scheduled( 'set_hours_event' ) ) {
        wp_schedule_event( 1451574000, '1hours', 'set_hours_event' );
    }
}
add_action('wp', 'my_activation');

//ボットの判別
function isBot() {
    $bot_list = array (
    'Googlebot',
    'Yahoo! Slurp',
    'Mediapartners-Google',
    'msnbot',
    'bingbot',
    'MJ12bot',
    'Ezooms',
    'pirst; MSIE 8.0;',
    'Google Web Preview',
    'ia_archiver',
    'Sogou web spider',
    'Googlebot-Mobile',
    'AhrefsBot',
    'YandexBot',
    'Purebot',
    'Baiduspider',
    'UnwindFetchor',
    'TweetmemeBot',
    'MetaURI',
    'PaperLiBot',
    'Showyoubot',
    'JS-Kit',
    'PostRank',
    'Crowsnest',
    'PycURL',
    'bitlybot',
    'Hatena',
    'facebookexternalhit',
    'NINJA bot',
    'YahooCacheSystem',
    'NHN Corp.',
    'Steeler',
    'DoCoMo',
    );
    $is_bot = false;
    foreach ($bot_list as $bot) {
        if (stripos($_SERVER['HTTP_USER_AGENT'], $bot) !== false) {
            $is_bot = true;
            break;
        }
    }
    return $is_bot;
}

24時間毎ではなく1週間毎にしたい場合、時間毎に配列を組んでいるところを曜日毎にし、リセット間隔を1日置きに変更すればできると思います。

単純にリセット間隔を1週間おきに変更するだけでは、リセット前後で集計期間が変わってしまいます。日曜日になったら前週の日曜日のデータを消去、月曜日になったら前週の月曜日のデータを…という動きにならなければ最新の1週間のデータにならない。(もっと正確に日曜の0時~23時で分けるならリセット間隔は24時間おき、配列は24時間×7日分で分けることになります。)

人気記事を表示する場所に追加するコード

<?php if( is_single() && !is_user_logged_in() && !isBot() ): //個別記事 かつ ログインしていない かつ 非ボット
set_post_views(); //アクセスをカウントする
endif; ?>

<?php
$args = array(
    'post_type'     => 'post',
    'numberposts'   => 8,       //表示数
    'meta_key'      => 'pv_count',
    'orderby'       => 'meta_value_num',
    'order'         => 'DESC',
);
$posts = get_posts( $args );
if( $posts ): ?>
    <?php foreach( $posts as $post ) : setup_postdata( $post ); ?>
        <dl class="popularlist">
            <dt>
                <a href="<?php the_permalink(); ?>" ><?php the_post_thumbnail( 'thumbnail' ); ?></a>
            </dt>
            <dd>
                <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
            </dd>
        </dl>
    <?php endforeach;
    wp_reset_postdata(); ?>
<?php else : ?>
    <p>アクセスランキングはまだ集計されていません。</p>
<?php endif; ?>