情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

【WordPress】リンク先エントリのページビュー数をリンクの横に表示する

JavaScript (15) PHP (25) WordPress (80) 正規表現 (4)

ブログ内リンクに、リンク先記事のページビューを表示する機能を実装しました。その実装方法をメモしておきます。こういう他のサイトが採用していない、謎機能を実装するのが好きです。正直邪魔だけど、リンク先について知りたい欲求に応える一つの手段として。

wordpress-link-with-page-view-sample

概要

次のような戦略で、PVを表示します。

まず、WordPressのテンプレートファイル(PHP)を編集して、エントリへリンクしている「aタグ」の中に、属性としてページビューを埋め込むフィルタを仕込みます

そして、JavaScriptで、そのページビューのデータを使用して、「○○PV」を作成します。

こうすることで、ページビューそのものがJavaScript実行前のHTMLには表示されないので、JavaScript+CSSで、デザインも簡単に変更できますし、表示しないのも簡単です。デザインとコンテンツの分離。

ページビューを取得する関数を用意する

兎にも角にも、WordPressの記事ID(postid)からページビューを取得する関数がなければどうすることもできません

私はWordPress Popular Postsプラグインを利用して、PVを取得できる関数「wpp_get_views」を作成していますが、同等の関数が用意できていれば、この後紹介する手順で、ページビュー表示が実装できます。

wpp_get_views関数を作成する方法は「WordPress:全記事にPV数を表示する方法メモ」で解説しています。

本文中のaタグにページビューを埋め込む

まず、ブログのテンプレートのPHPで、内部リンクのaタグに、そのaタグの属性という形で、ページビューを埋め込みます

どんな具合かというと、「<a href="(エントリURL)" ...」というソースを「<a href="(エントリURL)" data-wpp-views="(リンク先のページビュー)" ...」のように置換します

そのコードがこちらです。実行時に読み込まれるところに書けばいいので、例えばfunctions.phpに書きます。

function add_views_to_intra_link_handler ( $matches ) {
	$url = $matches[1];
	$postid = url_to_postid ( $url );
	return $matches[0] . ' ' . 'data-wpp-views="' . wpp_get_views ( $postid ) . '"';
}
function add_views_to_intra_link ( $content ) {
	$pattern_url = '/href="(http:\/\/did2memo\.net\/[0-9]{4}\/[0-9]{2}\/[0-9]{2}\/[-a-zA-Z0-9]+?\/)"/u';
	return preg_replace_callback ( $pattern_url , 'add_views_to_intra_link_handler' , $content );
}
add_filter('the_content', 'add_views_to_intra_link', 100 );

以下、補足説明。

add_filter(...)

最後のadd_filterで、本文のHTMLに add_views_to_intra_link関数でフィルタ(加工)を挟むようにしています。

add_views_to_intra_link関数

ここでは、本文全体($content)に対して、preg_replace_callback関数で置換をかけます。

$pattern_url

置換対象を$pattern_url変数に格納しています。

ここの正規表現はだいぶ緩いのですが、実用上問題ないはずです。

本ブログの個別ページのURLは、「http://did2memo.net/2014/01/01/post-name/」という形式なので、それをhref=""で指定している部分を置換するように指定しています。

このあと、URLを利用したいので、「href="(ココ)"」の部分をカッコで囲んで、後々コールバック関数で「matches[1]」で取得できるようにしています。

正規表現で特定した部分を、具体的に何に置換するのか、という部分はコールバック関数(add_views_to_intra_link_handler)で定義しています。

add_views_to_intra_link_handler 関数

add_views_to_intra_link_handler では、引数に $matches を受け取り、置換結果を返します。

この関数が、マッチした回数呼ばれます。

$matches[0]は、マッチした部分全体(href="http://.../")が格納されていて、$matches[1]に、1つ目のグループ(括弧で囲った部分、つまり、http://.../)が格納されています。

WordPressでは、何をするにもエントリのID (postid) を知る必要があるので、url_to_postid というWordPressの標準的な関数だけれどマイナーな関数を使って、postid に変換しています。

postidを入手したら、ページビューを取得する関数(wpp_get_views)を使って、PVに変換しています。

そして、そのページビューを使って、data-wpp-viewsという属性にページビューを埋め込んだ置換後のHTMLを返しています。

こんな流れで、目的の置換が実現されます。

JavaScriptで「○○PV」を表示する

aタグにデータが埋め込まれたので、あとはこれをブラウザ側のJavaScriptで表示します。もうJavaScriptでやりたい放題なので、例として、10000PV以下だと8,500PVのように表示し、10000PVより大きい時は2.3万PVのように表示するようにしてみました。

	$("a[data-wpp-views]").each(function(){
		var views = $(this).attr("data-wpp-views");
		var formatted_views = 0;
		if ( views > 10000 ) {
			formatted_views = ( Math.floor(views / 1000) / 10) + "万";
		} else {
			formatted_views = String ( views ).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,' );
		}

		var pv_a = $("<a />");
		pv_a.addClass("wpp-views");
		pv_a.attr("href", $(this).attr("href"));
		pv_a.html(formatted_views + '<span class="views">PV</span>');
		pv_a.insertAfter($(this));
	});

aタグにクラスは追加しなかったので、属性が存在しているかどうかで判定しています($("a[data-wpp-views]"))。

eachで、各aタグについて、function(){}で定義した操作を行います。

また、3ケタごとにカンマを入れる処理は「JavaScriptで数値を桁区切り (カンマ区切り) にする方法」を参考にしました。

残りは割と見たままです。結果だけ書くと、これで

<a href="http://did2memo.net/.../" data-wpp-views="246091" title="タイトル">リンク文</a>

というコードが、

<a href="http://did2memo.net/.../" data-wpp-views="246091" title="タイトル">リンク文</a><a class="wpp-views" href="http://did2memo.net/.../">24.6万<span class="views">PV</span></a>

のように編集されます(○○PVの部分が追加された)。

CSSで仕上げ

最後にCSSで見た目を仕上げます。

ここまで来ると、利用中のテンプレートにかなり依存しますが、とりあえずこのブログでどんなものを書いたのかを掲載しておきます。参考までに。

#contentleft .entry-body a[href*="//did2memo.net/"].wpp-views:link {
	background: none;

	margin-left: 1px;
	margin-right: 3px;

	vertical-align: super;

	color: #E56B21;
	font-size: 10px;
	line-height: 10px;
	border: 1px solid #E56B21;
	border-radius: 2px;
	text-decoration: none;
	}

コメント(0)

新しいコメントを投稿