Count per Dayをショートコードで使う
夏休みの最後にプログラムの難しい話しをします。
興味ない方スルーで^^
WordPressのプラグインを活用する
ショートコードを作成し、プラグインのメソッドを呼び出してカスタマイズする方法を紹介します。
この方法を使えば、デフォルトで用意されているデザインの変更だけでなく、どのような(ま、限界はありますが)カスタマイズも自由に行なえます。
以前にこちらで書いた内容があまりにも適当だったので、まじめに解説します。
はじめに
Count per Dayとは、サイトのアクセスを解析・表示してくれるWordPressのプラグインの1つです。
同じ端末をチェックし、同じ日であれば再カウントしないことが私の気に入っているところです。
他のページカウンタの多くはリロードを繰り返すだけでカウントアップしてしまい、精度に欠けます。
ただし、その分処理は重く何万と訪問者が訪れるようなページではサーバへの負荷が高くなるとのことです。
ここのようにアクセスが少ないサイトであれば全く問題はないようです(笑)
Count per Dayの標準で提供されるウィジェットはテキストベースのシンプルなものだけです。
もっと派手に活用してみたいと思われている方、その願い叶えましょう^^
表示内容の設計
ここで利用させてもらっているテーマのウィジェットは以下のような表示が基本デザインです。
- 見出し
ウィジェットの見出しです。文字の下に水色でラインが引かれます。 - 画像
主に投稿の見出しとなるイメージで、WordPressのアイキャッチ画像の縮小版です。 - 投稿の情報
タイトル、投稿日、アクセス数。 - 区切り線
投稿と投稿の区切り。
・サムネール、タイトル、投稿日、アクセス数
この4つが基本です。
ウィジェットの表示は、基本的にこのデザインに合わせることにします。
標準のCount per Dayではサムネールの表示は行えません。
よって、デザインだけでなく、サムネール表示も含めてカスタマイズします。
※ どのような表示とするかはセンス次第、デザイン能力に劣る私のようにテーマに合わせて統一させても良いですし、自分で好みのデザインにするも、もちろんです。
テーマに合わせた整形処理
「見出し」はウィジェットを追加すれば、同じに表示されると思いますので、その下の投稿の部分を整形する関数を用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/* テーマに合わせた投稿生成 ウィジェット用サムネール付き */ function guu_widget_display($lists, $view) { // 先頭</div>はウィジェットデフォルトを無効化するため必要 $html = '</div><div><ul class="recent-postcat">'; foreach($lists as $list) { // サムネ画像取得 $thumbnail_id = get_post_thumbnail_id($list->id); $img = wp_get_attachment_image_src($thumbnail_id, 'refer'); $url = preg_replace('/^http\:\/\/guu\.fmp\.jp/', '', get_permalink($list->id)); $html .= '<li class="has_thumb the-sidefeat-thumbnail">'; $html .= '<a href="' .$url .'" title="' .$list->title .'">'; $html .= '<img width="50" height="50" class="featpost alignleft" src="' .$img[0] .'"></a>'; $html .= '<div class="feat-post-meta">'; $html .= '<div class="feat-title">'; $html .= '<a href="' .$url .'" title="' .$list->title .'">'; $html .= $list->title .'</a></div>'; $html .= '<small>'; $html .= preg_replace('/([\d]+)-([\d]+)-([\d]+)(.*)/', '$1/$2/$3', get_post_field('post_date', $list->id)); if($view != 0 && $list->count > 0) { $html .= '<span class="widget-feat-comment">'; $html .= ' - '; $html .= number_format($list->count) .' reads'; $html .= '</span>'; } $html .= '</small>'; $html .= '</div>'; $html .= '</li>'; } $html .= '</ul>'; return $html; } |
配列で渡された投稿の情報を、その数分展開するだけです。
なお、アイキャッチが設定されていることを前提としてしまっています。
設定されていない方は、投稿中の画像を取得するなどに変更して下さい。
サムネール
ウィジェットへの表示処理で’refer’というサムネール画像を参照しています。
縦横比がおかしなサムネールは嫌なので、ハードクロップをtrue(切り抜き)で、画像は50×50の小さいサムネールを’refer’と定義し、追加しました。
1 2 3 4 |
/* サムネイル画像に50x50を追加 */ add_image_size('refer', 50, 50, true); |
サムネールはイメージをアップロードした時に作成されるようです(多分)
後からもう一度イメージを再アップロードなんてありえないので、こんなプラグインを利用すると楽に再構成できます。
・すべてのサムネイルの再生成を可能にします。 Regenerate Thumbnails
大変楽できました。ありがたいです。
さて、下準備は出来たので、どのようなウィジェットを作成していくか考えていきましょう。
最近の投稿ウィジェット
これは簡単で、新しくポストされた投稿を拾って、その投稿のアクセス数を取得するだけです。
指定の投稿に対してのアクセス数を取得するにはshow()メソッドを使用します。
‘show( $before, $after, $show, $count, $page )’
$before = text before number e.g. ‘<p>’ (default “”)
$after = text after number e.g. ‘reads</p>’ (default ” reads”)
$show = true/false, “echo” complete string or “return” number only (default true)
$count = true/false, false will not count the reads (default true)
$page (optional) PostID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* 最近の投稿をcpdのreads付きで表示 */ function guu_cpd_featured($atts2) { global $count_per_day; // デフォルトの配列 $atts1 = array( "limit" => 5, "view" => 1, ); // デフォルトの配列に引数で受け取った配列をマージ extract(shortcode_atts($atts1, $atts2)); $posts = get_posts(array('posts_per_page' => $limit)); foreach($posts as $post) { $hit[] = (object) array( 'id' => $post->ID, 'title' => $post->post_title, 'count' => $count_per_day->show("", "", false, true, $post->ID) ); } $html = guu_widget_display($hit, $view); return $html; } add_shortcode("cpd_featured", "guu_cpd_featured"); |
取得したデータを先ほど作った整形関数用に配列化して、呼び出すだけ。
この関数をショートコードとして、テキストのウィジェットなど用意すれば完成です。
ウィジェットの設定などは最後に説明します。
人気投稿のウィジェット
以下の画面で表示することとします。
・アーカイブページ
・トップページ
ちょっと工夫するのが、アーカイブページでの表示です。
アーカイブページとはカテゴリーやタグが選択された時に対象となる投稿を一覧する画面のことです。
表示投稿を絞っているので、その絞った投稿に関係する人気投稿のみを表示させたいですね。
例えば、こんな画面。
アーカイブページの例。
カテゴリー「創」を押すと、そのカテゴリーに含まれる投稿が一覧表示される。
ページ送りにも自動対応。
この場合は「創」カテゴリーに属する人気のある投稿だけを表示したい。
同様にタグ「音源モジュール」を選択した時のアーカイブ表示。
選択されたタグに絞った人気投稿の表示を行いたい。
実はCount per Dayのメソッドの仕様でこちらの時の処理が面倒。
何が面倒かはタグアーカイブの処理の説明参照。
ウィジェットの表示設計が済んだら、いよいよ処理の実装です。
カテゴリーアーカイブの処理
人気投稿を取得するメソッドgetMostVisitedPostIDs()は、カテゴリーをキーとして指定可能です。
‘getMostVisitedPostIDs( $days, $limit, $cats, $return_array )’
$days last x days, default = 365
$limit return max. x posts, default = 10
$cats IDs of categories to filter, array or number
$return_array true returns an array with Post-ID, title and count, false returns comma separated list of Post-IDs
アーカイブでカテゴリーがキーの場合は以下の処理となります。
なお、カテゴリーの階層には対応していないので、子カテゴリーを含む親カテゴリーを指定する場合は、get_term_children()などで子カテゴリーすべてを渡す必要があります。
※投稿に複数のカテゴリーが指定されている場合、訪問数がカテゴリー分合算されてしまうようです。
もし、そのような運用をされている場合は何らかの処理を加える必要があります。
バグなのか仕様なのかは不明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
function guu_cpd_thumbmail($atts2) { global $count_per_day; // デフォルトの配列 $atts1 = array( "days" => 0, "limit" => 10, "view" => 0, "title" => 0, "exclude_category" => '', ); // デフォルトの配列に引数で受け取った配列をマージ extract(shortcode_atts($atts1, $atts2)); if(is_category()) { $obj = get_category(get_query_var('cat')); $cat = get_term_children($obj->term_id, 'category'); if(! $cat) { // 子がなければ単独を指定 $cat = $obj->term_id; } $posts = $count_per_day->getMostVisitedPostIDs($days, $limit, $cat, true); foreach($posts as $post) { $hit[] = (object) array( 'id' => $post['id'], 'title' => $post['title'], 'count' => $post['count'], ); } } if($hit) { $html = guu_widget_display($hit, $view); } if($title == 1) { $ttl = "<small>" .$prefix ."人気記事 " .count($hit) ." 件"; if($days != 0) { $ttl .= " (過去 $days 日間)"; } $ttl .= "</small><p>"; } return $ttl .$html; } add_shortcode("cpd_thumbnail", "guu_cpd_thumbmail"); |
用意されたメソッドを呼び出すだけの簡単なお仕事です。
楽勝楽勝。
タグアーカイブの処理
さて、問題はタグをキーとしたい時。
いくつか思いついた処理方法を書き出してみます。
- カテゴリー指定無しで処理
Count per Dayのメソッドにカテゴリー指定なしで検索させます。
つまり、全件検索ということですね。
検索された投稿が指定された「タグ」に一致するものだけ抽出することで実装します。 - 所属カテゴリーを求めてから処理
指定された「タグ」を含む投稿を検索、その投稿が所属するカテゴリーを再度検索し、ストックします。
重複したカテゴリーをサマリしてカテゴリーリストを作れば後はカテゴリーアーカイブと同様の処理で実装出来ます。 - Count per Dayのメソッドに頼らず、自前で処理
カテゴリーをキーとして自力で投稿を検索し、その結果に閲覧数を付与することで実装します。
検索処理やら、ソート処理やら全部自前でやらないといけません。
さらに、それぞれを検討してみます。
- これはダメです。
何のためのDBインデックスなのかわかりません。こんな処理を実装しているようではプログラマなんて名乗れません。
よって問答無用で却下。 - それぞれの関係をインデックス利用して検索していますが、ちょっと冗長すぎ。
ヒットするであろう投稿を二度検索してしまうのもなんだか間抜けです。
プログラマだったら、こんな無駄な検索の仕方はDB設計者に申し訳ないと思いましょう。 - タグがキーなんですから、そこを基準に検索し始めるのが一番ですね。
プログラムを書くのがプログラマのお仕事。
なので、リレーション活かした処理をしてやりましょう。
ということで、これを採用。
結論として、Count per Dayで用意されたメソッドを使ってカテゴリーをキーとしようとするため無理が出るので、人様に頼らず自前で処理をしてしまいましょう。
絞り込みの処理自体はDBが、ソートはPHPの関数がやってくれます。
実は何も自分ですることがありません(笑)
※この処理では、期間を指定しての訪問数は取得できません。ご注意を。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
if(is_tag()) { // タグ指定のアーカイブ表示 $tag = get_tag(get_query_var('tag_id')); $search_args = array( 'tax_query' => array( array( 'taxonomy' => 'post_tag', 'field' => 'term_id', 'terms' => $tag->term_id ) ) ); // タグをキーにして絞り込み $posts = get_posts(array('posts_per_page' => -1) +$search_args); // カウントを取得 foreach($posts as $post) { $cnt = $count_per_day->show("", "", false, true, $post->ID); if($cnt) { $hit[] = (object) array( 'id' => $post->ID, 'title' => $post->post_title, 'count' => $cnt, ); } } if($hit) { // カウントでソート usort($hit, function($a, $b) { return ($a->count < $b->count) ? 1 : -1; } ); // 表示数制限 if($limit > 0) array_splice($hit, $limit); } } |
これですっきり。
まとめ
トップページと検索アーカイブページへの対応を追加してまとめたものが以下となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
/*=============================================== Count par Dayの関数をコールしてサムネ付きウィジェット */ /* サムネイル画像に50x50を追加 */ add_image_size('refer', 50, 50, true); /* Count par Dayの集計を元にサムネール付きウィジェット表示 */ function guu_cpd_thumbmail($atts2) { global $count_per_day; // デフォルトの配列 $atts1 = array( "days" => 0, // 全期間 "limit" => 10, "view" => 0, "title" => 0, "exclude_category" => '', ); // デフォルトの配列に引数で受け取った配列をマージ extract(shortcode_atts($atts1, $atts2)); if(is_category()) { $obj = get_category(get_query_var('cat')); $cat = get_term_children($obj->term_id, 'category'); if(! $cat) { // 子がなければ単独を指定 $cat = $obj->term_id; } if($days == 0) { $search_args = array( 'tax_query' => array( array( 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => $obj->term_id ) ) ); } $prefix = "『{$obj->description}』の"; } elseif(is_tag()) { // タグ指定のアーカイブ表示 $tag = get_tag(get_query_var('tag_id')); $search_args = array( 'tax_query' => array( array( 'taxonomy' => 'post_tag', 'field' => 'term_id', 'terms' => $tag->term_id ) ) ); $prefix = "『" .guu_tag_filter($tag->name) ."』の"; } else { // カテゴリー指定なし(すべて) // トップや検索アーカイブなど $cat = get_categories(array( 'exclude' => $exclude_category )); } // 対象投稿取得 if($search_args) { // タグをキーにして絞り込み $posts = get_posts(array('posts_per_page' => -1) +$search_args); // カウントを取得 foreach($posts as $post) { $cnt = $count_per_day->show("", "", false, true, $post->ID); if($cnt) { $hit[] = (object) array( 'id' => $post->ID, 'title' => $post->post_title, 'count' => $cnt, ); } } if($hit) { // カウントでソート usort($hit, function($a, $b) { return ($a->count < $b->count) ? 1 : -1; } ); // 表示数制限 if($limit > 0) array_splice($hit, $limit); } } else { $posts = $count_per_day->getMostVisitedPostIDs($days, $limit, $cat, true); foreach($posts as $post) { $hit[] = (object) array( 'id' => $post['id'], 'title' => $post['title'], 'count' => $post['count'], ); } } if($hit) { $html = guu_widget_display($hit, $view); } if($title == 1) { $ttl = "<small>" .$prefix ."人気記事 " .count($hit) ." 件"; if($days != 0) { $ttl .= " (過去 $days 日間)"; } $ttl .= "</small><p>"; } return $ttl .$html; } add_shortcode("cpd_thumbnail", "guu_cpd_thumbmail"); /* 最近の投稿をcpdのreads付きで表示 */ function guu_cpd_featured($atts2) { global $count_per_day; // デフォルトの配列 $atts1 = array( "limit" => 5, "view" => 1, "exclude_category" => '', ); // デフォルトの配列に引数で受け取った配列をマージ extract(shortcode_atts($atts1, $atts2)); $posts = get_posts(array('posts_per_page' => $limit)); foreach($posts as $post) { $hit[] = (object) array( 'id' => $post->ID, 'title' => $post->post_title, 'count' => $count_per_day->show("", "", false, true, $post->ID) ); } $html = guu_widget_display($hit, $view); return $html; } add_shortcode("cpd_featured", "guu_cpd_featured"); /* テーマに合わせた投稿生成 ウィジェット用サムネール付き */ function guu_widget_display($lists, $view) { // 先頭</div>はウィジェットデフォルトを無効化するため必要 $html = '</div><div><ul class="recent-postcat">'; foreach($lists as $list) { // サムネ画像取得 $thumbnail_id = get_post_thumbnail_id($list->id); $img = wp_get_attachment_image_src($thumbnail_id, 'refer'); $url = preg_replace('/^http\:\/\/guu\.fmp\.jp/', '', get_permalink($list->id)); $html .= '<li class="has_thumb the-sidefeat-thumbnail">'; $html .= '<a href="' .$url .'" title="' .$list->title .'">'; $html .= '<img width="50" height="50" class="featpost alignleft" src="' .$img[0] .'"></a>'; $html .= '<div class="feat-post-meta">'; $html .= '<div class="feat-title">'; $html .= '<a href="' .$url .'" title="' .$list->title .'">'; $html .= $list->title .'</a></div>'; $html .= '<small>'; $html .= preg_replace('/([\d]+)-([\d]+)-([\d]+)(.*)/', '$1/$2/$3', get_post_field('post_date', $list->id)); if($view != 0 && $list->count > 0) { $html .= '<span class="widget-feat-comment">'; $html .= ' - '; $html .= number_format($list->count) .' reads'; $html .= '</span>'; } $html .= '</small>'; $html .= '</div>'; $html .= '</li>'; } $html .= '</ul>'; return $html; } |
自分のサイトに合わせて、自由に変更して利用して下さい。
ウィジェット設定
すべてテキストウィジェットを作成し、既存のウィジェットが不要なら置き換えるだけです。
おしまい
Count per Dayはユーザーが自由にデータを使えるようになっています。
PHPを直接扱わなくても、ショートコードを使えば投稿中に様々な情報を出すことも可能です。
詳しくはこちらを参照下さい。
次回はYARPP(Yet Another Related Posts Plugin)をショートコードで制御するお話しの予定です。
いつになるかはわかりません^^
コメントを残す