Word Pressの投稿の閲覧回数を記録して、人気の記事として表示できるプラグインはいくつかありますが、ショートコードで出力されるソースコードがイマイチで、手を加える必要がでてきました。 条件にあったプラグインを探すのも手間ですし、せっかく記録された閲覧回数も引き継げないのでそのまま使わねば。と、いうことでショートコードを使わずにget_postsで出力しちゃいます。

ショートコードを使わず出力する(Jetpack Post Viewsの場合)

// オプション
$args = array(
	'showposts'		=> 5, // 表示する件数
	'post_type'		=> 'post',
	'orderby'		=> 'meta_value_num', // カスタムフィールドの内容を数値として扱う
	'meta_key'		=> 'jetpack-post-views', // カスタムフィールド名
	'order'		=> 'DESC' // 並び替えの順番 ASC:昇順、DESC:降順
);
$popularity_posts = get_posts($args); // 記事を得る
// 得られた記事を出力
foreach ( $popularity_posts as $post ):
	setup_postdata( $post ); // 取得した記事のセットアップ
	echo '<li><a href="' . get_permalink() . '"><span class="view">'.get_post_meta( $post->ID, 'jetpack-post-views', true ).' views</span>'. get_the_title() . '</a></li>';
endforeach;
wp_reset_postdata(); // ← これをわすれないで
ようするに、プラグインのデータはカスタムフィールドに保存されているので、それでソートして記事を取得してるわけです。 カスタムフィールドの名前を変えた時は、20行目の get_post_meta( $post->ID, ‘jetpack-post-views’, true ) を変更するのも忘れないでください。 これでもう自由自在ですね。 ちなみに、 Jetpack Post Viewsが「jetpack-post-views」、 WP-PostViewsが「views」に閲覧回数が記録されています。

さらに細かく条件を指定する

プラグイン以上のことができないとあんまり意味がないですよね。 この際なのでもっと徹底的にカスタマイズしてみましょう。

n回以上閲覧されたものだけ

少なすぎる閲覧数のものは除きます。 上述のコードに、複数条件で抽出するため meta_query を追加します。
$args = array(
	'showposts'		=> 5, // 表示する件数
	'post_type'		=> 'post',
	'orderby'		=> 'meta_value_num', // カスタムフィールドの内容を数値として扱う
	'meta_key'		=> 'jetpack-post-views', // カスタムフィールド名
	'order'		=> 'DESC', // 並び替えの順番 ASC:昇順、DESC:降順
	'meta_query'  => array(
		array(
			'key'     => 'jetpack-post-views',  // 対象のカスタムフィールド名
			'type'    => 'NUMERIC', // データのタイプは数値(閲覧数なので)
			'value'    => 800, // 指標とする値(閲覧数800)
			'compare' => '>=' // 指標以上 <= とすると value 以下になる
		)
	)
);
echo '<ul>';
$popularity_posts = get_posts($args);
foreach ( $popularity_posts as $post ):
	setup_postdata( $post );
	echo '<li><a href="' . get_permalink() . '"><span class="view">'.get_post_meta( $post->ID, 'jetpack-post-views', true ).' views</span>'. get_the_title() . '</a></li>';
endforeach;
wp_reset_postdata(); // ← これをわすれないで
echo '</ul>';
上のサンプルだと閲覧数が800未満のものは表示されなくなります。

n件以上で、かつn’件以上のものは除く

meta_queryは配列を増やせば複数の指定ができます。 常に上に表示されているあの記事をハブることもできます。
'meta_query'  => array(
	'relation' => 'AND', // 複数の条件の時は論理演算子も。AND = 両方一致、 OR = どちらかが一致...
	array(
		'key'     => 'jetpack-post-views',  // 対象のカスタムフィールド名
		'type'    => 'NUMERIC', // データのタイプは数値(閲覧数なので)
		'value'    => 800, // 指標とする値(閲覧数800)
		'compare' => '>=' // 指標以上 <= とすると value 以下になる
	),
	array(
		'key'     => 'jetpack-post-views',
		'type'    => 'NUMERIC',
		'value'    => 3000, // 指標とする値(閲覧数3000)
		'compare' => '<' // 未満
	)
)
上のサンプルだと閲覧数が800未満のものと3000より上のものは表示されなくなります。

投稿日時で絞り込む

古い記事が上位にでてきてもちょっとなぁって時は、日付で範囲を指定しましょう。 日付を絞り込む関数をつくって、add_filter でフックします。

1ヶ月前以内の記事だけ表示する

// 日付を絞り込むためのユーザー関数を作る
function custom_posts_where_before_nday($where = '') {
	global $wpdb;
	$where .= $wpdb->prepare( " AND post_date BETWEEN %s AND CURTIME()", date( 'Y-m-d', strtotime('-1 month') ) ); // 1ヶ月以内
	return $where;
}

$args = array(
	'suppress_filters'	=> false,
	'showposts'		=> 5, // 表示する件数
	'post_type'		=> 'post',
	'orderby'		=> 'meta_value_num', // カスタムフィールドの内容を数値として扱う
	'meta_key'		=> 'jetpack-post-views', // カスタムフィールド名
	'order'		=> 'DESC', // 並び替えの順番 ASC:昇順、DESC:降順
	'suppress_filters' => false // 標準のフィルターを無効にする
);
echo '<ul>';
add_filter( 'posts_where', 'custom_posts_where_before_nday' ); // 絞り込むフィルターにユーザー関数をフック
$popularity_posts = get_posts($args);
foreach ( $popularity_posts as $post ):
	setup_postdata( $post );
	echo '<li><a href="' . get_permalink() . '"><span class="view">'.get_post_meta( $post->ID, 'jetpack-post-views', true ).' views</span>'. get_the_title() . '</a></li>';
endforeach;
wp_reset_postdata();
echo '</ul>';
remove_filter( 'posts_where', 'custom_posts_where_before_nday' );  // ← フックした関数を取り除く
上のサンプルだと今日から1ヶ月前に投稿した記事だけ表示されます。 “-1 month”の部分を”-1 week”にすると1週間前、”-3 day”に変えると3日前になります。

suppress_filters = falseのパラメーターを追記しました。 これがないとposts_whereにフィルターをフックしても無視されてしまうようです。

2014年9月26日 – 上記サンプルを修正しました。 修正前: $wpdb->prepare( ” AND post_date > %s”, date( ‘Y-m-d’, strtotime(‘-1 month’) ) ); 修正後: $wpdb->prepare( ” AND post_date BETWEEN %s AND CURTIME()”, date( ‘Y-m-d’, strtotime(‘-1 month’) ) );

修正後の方が、データベースのインデックスが利用され高速に動作するはずです。

まとめ

プラグインのショートコードを使わずに、WordPress本来の関数で出力すれば、閲覧数にプラスαで色々な条件で記事を呼び出せます。 人気記事からのページ移動が多いなら、カスタマイズしてみるとユーザーの流れがもっとキレイになるかもしれません。

何か一言あれば!!

質問とかツッコミとかお気軽にコメントしてください。がんばって返します。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

9 件のコメント

  1. ピンバック: 2013年12月時点で当サイトで絶賛稼働中のWordPressプラグイン25種類 - cocowa

  2. 初めまして。質問させていただいても宜しいでしょうか。
    こちらの最後にある「1ヶ月前以内の記事だけ表示する」にカテゴリーを追加したい場合、どのようなコードを追加すれば問題が解決するのでしょうか。

    日付やアイキャッチなどは表示する事が出来たのですが、get_the_categoryなどでカテゴリーを表示させようとした場合に「array」と表示されてしまいます。

    もし宜しければお教え頂けませんでしょうか。

    1. よっしー 投稿作成者

      匿名様
      はじめまして!
      返信が遅くなってしまい申し訳ございませんでした。

      質問の「カテゴリーを表示させたい」につきましてお返事を書きます。
      結論から申します。

      “その記事が属するカテゴリーのリンクをすべて表示したい場合”は、
      WordPressの関数 get_the_category_list() を使い、

      
      

      で、可能です。

      普通のリンクではなくもっとカスタマイズしたい場合は、
      以下のサンプルコードのように、カテゴリーをひとつひとつ記述するとわかりやすいと思われます。

      “その記事が属するカテゴリーを1つだけ表示させたい場合”、

      # サンプルコード A

      name;
      // 0番目のカテゴリーのURLを取得
      $category_url = get_category_link($category->term_id);
      // 表示
      echo '' . $category_name . '';
      ?>
      

      “その記事が属するカテゴリーをすべて表示させたい場合”は、

      # サンプルコード B

      name;
        // カテゴリーのURLを取得 
        $category_url = get_category_link($category->term_id);
        // ↓表示
        echo '' . $category_name . '';
      // ループ終了
      }
      ?>
      

      以上です。

      この記述の説明は少し長くなりますので、結果とはわけて↓に書きます。

      PHPで【関数】を実行すると、“文字列”、“配列”、“オブジェクト”等といった関数に応じた《返り値》を得られます。
      その返り値を『変数』に代入して操作したり表示させたりします。

      さて、上記のサンプルコードの頭の方にある

      $category = get_the_category();
      

      ですが、これは、$categoryという『変数』に get_the_category() の《返り値》を代入するという記述です。

      get_the_category() の返り値は、カテゴリーの情報オブジェクトの入った“配列”で、

      $category[0]
      $category[1]
      $category[2]


      と、その記事のカテゴリーの情報が配列になっています。
      $category[0],$category[1]・・・はそれぞれカテゴリーの情報の入ったオブジェクトです。

      問題は、“配列”や“オブジェクト”の情報の表示のさせ方です。

      “文字列”ならば echo や という記述でその文字列を表示させられます。
      しかし、“配列”を echo しても、「array」としか表示されず、
      “オブジェクト”を echo しても、何も表示されなかったりエラーが発生したりします。

      そこで何番目の配列の、オブジェクトのどの位置なのかを指定する必要があります。

      まずサンプルコード A の6行目で、

      $category = $categories[0];
      

      配列のうち最初の1つ(0番目)を指定しています。

      この時、$category[0]はオブジェクトなので、文字列として表示させられません。
      そこでオブジェクトの中身を指定します。

      そのカテゴリーの名前の“文字列”は、
      サンプルコード Aの8行目

      $category_name = $category->name;
      

      ここで、オブジェクトの name を取得しています。

      そのカテゴリーのURLの“文字列”は
      サンプルコード Aの10行目

      $category_url = get_category_link($category->term_id);
      

      で、 get_category_link() にそのカテゴリーのID(term_id)を指定して取得しています。

      そして カテゴリーの名前とURLを使い、リンクを echo しています。

      echo '' . $category_name . '';
      

      サンプルコード Bも、基本はAと同じです。
      Aのように$categories[0] と配列を指定せず、配列をループで1つずつ取得して表示しています。

      以上です。
      長々となってしまいましたが、
      よく見かけるリンク付きのカテゴリーリストの場合でしたら、
      冒頭のようにWordPressの関数を利用することで簡潔にかけると思われます。

  3. よっしー 投稿作成者

    記事のサンプルコードの修正のお知らせです。

    記事内にも書いておりますが、以下のようにサンプルコードを修正いたしました。

    2014年9月26日 –
    記事内、「1ヶ月前以内の記事だけ表示する」 のサンプルコードを修正しました。
    修正前:

    $wpdb->prepare( " AND post_date > %s", date( ‘Y-m-d’, strtotime(‘-1 month’) ) );
    

    修正後:

    $wpdb->prepare( " AND post_date BETWEEN %s AND CURTIME()", date( ‘Y-m-d’, strtotime(‘-1 month’) ) );
    

    修正後の方が、データベースのインデックスが利用され高速に動作するはずです(きっちりと検証してませんがセオリー的なものです)

  4. よっしーさん
    ぬおおおお、ありがとうございます!!!

    凄い細かく説明していただき本当に感謝です!
    プログラム的な事をはじめたばかりで苦戦していたのですが、コード部分以外の説明も詳しく記載していただき感謝感激です! なぜこうなるのかが疑問だったのでとてもスッキリしました!
    これは保存させていただきます!

    よっしーさんはわたしの神様です!!
    本当に本当にありがとうございます!!

    1. よっしー 投稿作成者

      匿名様
      こんにちは~。解決できたようでなりよりです。
      WordPressはベースができているのでイチからつくるよりは取っ付き易いですが、カスタマイズとなるとやはりPHPの多少の理解は必要になってきますね(´・ω・`)

      PHPの動きにも慣れてきてWordPressをつくりこんでいくうちに、WordPressの独自の関数では物足りない部分がでてくると思います。
      そうなってくれば、WordPressのソースコードでその関数がどう実装されているかを調べて、それを真似しつつカスタマイズした関数を実装したりと、もっと楽しくなってくると思います!

      わたしもまだまだ全然なので・・・お互いお勉強がんばりましょう(´ω`)

  5. ピンバック: 人気記事ランキングプラグイン「WordPress Popular Posts」と「WP-PostView」の機能比較 | シーズクリエイターズブログ

  6. はじめまして。
    一番上のコードを使用させてもらってます。
    2つ質問よろしいでしょうか?

    1
    出力結果がjetpackのサイト統計情報->すべて日間の人気記事と異なるのですが、これは致し方ないことなのでしょうか?

    2
    統計期間の指定はできますでしょうか?
    例えば-1で全期間、7で一週間、30で一ヶ月等

    よろしくお願い致します!

  7. 連投失礼致します。
    stats_get_csvの方で意図した表示にできました。
    重ね重ね失礼致しました。