SNSのカウントをキャッシュするWordPressのプラグインを作成しました


投稿日:2015年8月15日
  • 5
  • 1
  • 28



Step by Step Social Count CacheというWordPressのプラグインを作りました

sbsscc

簡単に言えば、SNSのカウントをキャッシュするプラグインです。

投稿の最終更新日から「1日」「1日~1週間」「1週間以降」の3つの段階で、キャッシュの有効期限を設定することができます。

条件が揃えば、1度キャッシュしたカウントは平均2msで表示が可能になり、実に1000倍も高速に表示することができます

プラグインの公式ページ」からダウンロードするか、プラグインの検索ページで「Step by Step Social Count Cache」と検索していただければ表示されます。

この解説はバージョン1.6で有効です。

1.4以前のバージョンからアップデートした場合、1度プラグインを停止し、再度有効にしてください。

プラグインの特徴と設定方法

カウントをキャッシュするSNSは5種類

具体的にはTwitterFacebookGoogle+はてなブックマークPocketfeedly6種類です。
(Twitterのカウントはcount.jsoon APIを利用しています。カウントを有効にするには、事前にwidgetoon.js & count.jsoonでサイト登録をする必要があります。未登録だと「-1」と表示されます。)

取得するSNSはオプションページで変更することができます。

sbsscc05

表示の有無にかかわらず、チェックの入っているSNSのカウントを取得してキャッシュします。実行速度に直結するため、必要のないSNSのチェックは外してください。

キャッシュ期間は3段階

投稿の最終更新日から、「1日」「1日~1週間」「1週間以降」の3つの段階で、キャッシュの有効期限を設定することができます。

それぞれのキャッシュ期間はオプションページで分単位で調整することができます。

sbsscc02

FacebookのApp Tokenが必要

Facebookの「いいね」ですが、App Tokenが不要なAPIは廃止が決定しています。既にFacebookが提示した期限は過ぎており、いつ取得できなくなってもおかしくない状態です。

2015年8月現在、最新のAPI 2.4はApp Tokenが必要です。「Facebookの解説ページ」を参考にApp Tokenを取得してください。
App Tokenはオプションページで設定できるようにしました。

sbsscc03

Tokenの値が間違っている場合、設定ページで「FacebookのApp Tokenが誤っています。値を確認してください。」というエラーメッセージが表示されます。

追記

tokenの取得方法の質問を頂いたので解説します。
まずFacebookのDeveloperページでアプリを登録します。アプリのページでApp IDと、App Secretをメモします。

sbsscc06

続いてWordPressのfunctions.phpに以下のように記述してアクセスしてみてください。

$app_id = "0000000000000000"; // App ID
$app_secret = "00000000000000000"; // App Secret

$token_url = "https://graph.facebook.com/oauth/access_token?" .
"client_id=" . $app_id .
"&client_secret=" . $app_secret .
"&grant_type=client_credentials";

$access_token = wp_remote_get( $token_url );

var_dump($access_token);

すると「access_token=000000000000|4OsdafgagvadwxVkXdafnHguU(サンプル)」といった値が出力されます。「access_token=」以降がApp Tokenです。

もちろん普通に「https://graph.facebook.com/oauth/access_token?client_id=$app_id&client_secret=$app_secret&grant_type=client_credentials」で$app_id$app_secretを置き換えてブラウザでアクセスしても取得できます。

feedlyでカウントするRSSは自由に設定可能

WordPressは自動でRSS、RSS2、Atomのフィードが書きだされます。一般によく使われているのはRSS2のFeedで、URLは「http://example.com/?feed=rss2」です。
カスタムのパーマリンクを設定している場合は静的URLで「http://example.com/feed/」等になります。

このプラグインでは上記の2つのパターンには対応しますが「パーマリンクは静的だけど、Feedは動的なURLを使いたい。」または「独自に作成したFeedを使用したい。」といった需要もあるようなのでFeedを指定できるようにしました。

sbsscc04

キャッシュのプリロードが可能

通常カウントのキャッシュは、ページを読み込んだ時点で作成されます。

6つのSNS全てのカウントを取得すると1~2秒かかります。一覧ページで10ページ表示したとして、初回閲覧時に20秒もかかる計算になります。

そこで「バックグランドで先回りしてカウントをキャッシュしよう」というのがプリロード機能です。

プリロードはWordPressの擬似cronを使っています。投稿のステータスが公開になっているページを、5分間に5ページずつ取得します。
かなりゆったりとしたペースですが、同時接続数の厳しいレンタルサーバ等でも余裕を持って使えるように設定しました。
全ページを網羅すると自動で停止するので、サーバに負荷をかけ続けることもありません。

sbsscc05

注意点として、WordPressのcronを停止していると動作しません。
また、プラグインディレクトリにファイルを保存する関係で、プラグインディレクトリに対する書き込み権限が必要です。

プリロードでは1度キャッシュしたページのカウントは再取得しません。キャッシュを全て削除して再取得したい場合はプラグインの設定画面で1度プラグインを停止して、有効にした後にプリロードを実行してください。

APCもしくはAPCuが有効な場合にクエリをキャッシュ

PHPのユーザーキャッシュ機能であるAPCもしくはAPCuを利用して高速化しています。

キャッシュしたカウントをデータベースから取得して表示するのに6msかかります。APCが有効な場合は2msで表示できるようになります。通常の方法でカウントを取得すると、遅い場合は2秒程度かかるので、実に1000倍の速度でカウントを表示することが可能です。


プラグインの使い方

カウントを表示する方法

投稿のキャッシュを全て取得して書き出す方法。
返り値は変数なので、それぞれのSNS名を添え字にしてカウントを出力します。

複数取得する場合はパフォーマンス的にこちらをお勧めします。

<?php
	$socal_count = sbs_get_all();
	echo $socal_count["all"]; // 全てのSNSの合計を返す
	echo $socal_count["twitter"];
	echo $socal_count["facebook"];
	echo $socal_count["google"];
	echo $socal_count["hatena"];
	echo $socal_count["pocket"];
	echo $socal_count["feedly"];
?>

もしくは個別に取得して書き出す方法。

<?php
	echo sbs_get_twitter();
	echo sbs_get_facebook();
	echo sbs_get_google();
	echo sbs_get_hatena();
	echo sbs_get_pocket();
	echo sbs_get_feedly();
?>

カウントの数値を返すだけなので、パラメータ等はありません。

デザインされたボタンを表示する方法

以下の2つのタイプを作成しました。

バルーンタイプ

sbs_ba_sq01

カウントを上に表示するタイプです。
このサイトでも記事の下に表示しています。

<?php
    $args = array( "hatena", "twitter", "google", "facebook", "pocket", "feedly" );
    sbs_balloon_style( $args );
?>

パラメータ

$args

“hatena”, “twitter”, “google”, “facebook”, “pocket”, “feedly”のいずれかを配列で指定します。指定した順序によって表示順が変更になります。

表示する要素は順序を変えたり

sbs_ba_sq02

必要な要素だけ選んだり

sbs_ba_sq03

といったカスタマイズが可能です。

スクエアタイプ

sbs_ba_sq04

モノトーンの四角でカウントを表示するタイプです。
このタイプもバルーンタイプと同じように要素を並べ替えたり、必要な要素だけ表示する事ができます。

<?php
    $args = array( "hatena", "twitter", "google", "facebook", "pocket", "feedly" );
    sbs_square_style( $args );
?>

パラメータ

$args

“hatena”, “twitter”, “google”, “facebook”, “pocket”, “feedly”のいずれかを配列で指定します。指定した順序によって表示順が変更になります。

カウントの多い投稿のIDを取得する方法

SNSでカウントの多い順に投稿を表示したい」という需要もあるようなので、追加しました。
このブログでも試験的に導入してみました。動作サンプルはサイドバーにある「SNSで人気の投稿」というタグをご覧ください。

<?php
	sbs_get_pp_all( $page, $post_type );
?>

パラメータ

$page

取得する投稿の数を指定する。初期値(省略時):10ページ。

$post_type

取得するポストタイプを指定する。初期値(省略時):post。

戻り値

全てのSNSのカウントを合計して、カウントが多い順に投稿のIDを配列で返す。

デフォルトの使い方

投稿タイプがpostの投稿を、カウントが多い順に10ページ表示する例。

<?php
	$page = 10; // 表示するページ数
	$post_type = 'post'; // 表示するポストタイプ
	$args = array(
		'post_type' => $post_type,
		'posts_per_page' => $page,
		'orderby' => 'post__in',
		'post__in' => sbs_get_pp_all( $page, $post_type ),
	);
?>

<?php $wp_query = new WP_Query( $args ); ?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>

<!-- ここにタイトルやサムネイルなどを指定する -->
<?php the_title(); ?>

<?php endwhile; ?>
<?php wp_reset_query(); ?><!-- 忘れずにリセットする必要がある -->

サブループの記述方法は、様々ありますがメインクエリを元に戻すことを忘れないようにしてください。
一旦メインクエリを「$temp = $wp_query」等で保存しておいて、wp_reset_query()の代わりに「$wp_query = $temp」で戻すこともできます。

<?php
	$page = 10;
	$post_type = 'post';
	$args = array(
		'post_type' => $post_type,
		'posts_per_page' => $page,
		'orderby' => 'post__in',
		'post__in' => sbs_get_pp_all( $page, $post_type ),
	);
	$temp = $wp_query // 一旦クエリを保存
?>

<?php $wp_query = new WP_Query( $args ); ?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>

<?php the_title(); ?>

<?php endwhile; ?>
<?php $wp_query = $temp; ?><!-- ここで戻す -->

さらに詳しく知りたい方は「WordPressの新・旧ループからカスタムクエリ・アーカイブまで徹底解説」をご覧ください。

以下のタグを使えば特定のSNSのみのカウント順に投稿IDを取得できます。

<?php
	sbs_get_pp_twitter( $page, $post_type );
	sbs_get_pp_facebook( $page, $post_type );
	sbs_get_pp_google( $page, $post_type );
	sbs_get_pp_hatena( $page, $post_type );
	sbs_get_pp_pocket( $page, $post_type );
?>

バルーン・スクエアタイプのタグはカスタマイズ可能

設定画面でsbs_balloon_style() もしくは sbs_square_style() のタグをカスタマイズすることができます。

PHPのコードは使えないので、「ページのURL」等を指定するには以下のカスタマイズ用のタグを利用してください。

[[url]] ページのURL
[[site_title]] サイト名
[[title]] ページのタイトル
[[count]] それぞれのSNSのカウント数

例)twitterの表示を「Tweet」から「List」に変更

<li class="twitter_count"><div class="bubble"><a href="https://twitter.com/intent/tweet?original_referer=[[url]]&text=[[title]]%20%7C%20[[site_title]]&tw_p=tweetbutton&url=[[url]]&via=[[site_title]]" class="count" target="_blank">Tweet</a></div><a class="bgimage" href="https://twitter.com/intent/tweet?original_referer=[[url]]&text=[[title]]%20%7C%20[[site_title]]&tw_p=tweetbutton&url=[[url]]&via=[[site_title]]" class="count" target="_blank"></a></li>
<li class="twitter_count"><div class="bubble"><a href="https://twitter.com/intent/tweet?original_referer=[[url]]&text=[[title]]%20%7C%20[[site_title]]&tw_p=tweetbutton&url=[[url]]&via=[[site_title]]" class="count" target="_blank">List</a></div><a class="bgimage" href="https://twitter.com/intent/tweet?original_referer=[[url]]&text=[[title]]%20%7C%20[[site_title]]&tw_p=tweetbutton&url=[[url]]&via=[[site_title]]" class="count" target="_blank"></a></li>

バルーンタイプ、スクエアタイプ共に別々のカスタマイズが可能です。

空欄にして設定を保存するとデフォルトの設定がセットされます。


デバッグモードの実装

バージョン1.6より隠し機能としてデバッグモードを実装しました。
sbs-social-count-cache.php1092行目あたり

	$debug_mode = false;

となっているところを

	$debug_mode = ture;

としてください。

するとソース上で以下のようにキャッシュ関連の情報が表示されます。

<!--
SBS Social Count Cacheデバックモード
投稿の最終更新日から:1週間以上経過
サーバのapc cache:有効
apc cache:見つかった
サイトのローカルタイム:2017-04-29 15:24:12
投稿の最終更新日時:2016-05-13 17:23:28
キャッシュの取得時間:2017-04-26 09:26:04
キャッシュの有効期限:2017-05-03 09:26:04
キャッシュの残り時間:324112秒
キャッシュ:期限内
-->

この情報を元にキャッシュが正しくされているか調べることができます。
また、正しく反映されない場合にも原因の追求にご利用ください。


プラグイン作成後記

SNSのボタンは、ブログに留まらずニュースやコーポレートサイトでも欠かせないものになりました。
しかし汎用的になったが故に、動作の重いものになってしまいました。

サーバの動作を1ms秒単位で調整している身としては、その重さが看過できないものになってきました。
そこでPHPでカウントだけを取得したり、JavaScriptで非同期に取得する方法も試しましたが、納得のできる速度は出ませんでした。

Nginxのリバースプロキシで長めにキャッシュすることでお茶を濁していましたが、これにも問題がありました。
投稿してすぐに拡散された記事の場合、反響を反映するまで時間がかかりました。

キャッシュを長くすると投稿から間もない反響を反映できないキャッシュを短くすると満足な速度が出ない、そんなジレンマを抱えていました。

そこで、記事を作成してからの経過時間でキャッシュ期間を変更するという仕組みを思いつきました。

個人的に運用してみて経過も良好だったので「練習がてらプラグインを作成してみよう」というのがきっかけです。
実際に公開するにあたり、タグが被らないように前置詞を付けたり、アンインストール時に作成したデータベースやオプションを削除したりと、個人用では必要のなかった調整に、なかなか骨が折れました。
プラグインの作成より、公開するための作業のほうがずっと大変でしたw

もしよかったら動作テストを兼ねて利用してみてください。
フィードバックもいただけたら嬉しいです。

純日本語プラグイン

日本人による、日本のブログ向けのプラグインなので「プラグインページ」の表記を日本語にしました。

作者の拙い英語で日本人も外国人も戸惑わせるくらいなら、きっぱりと日本向けにしたほうが混乱も少なかろうという判断です。

考えてみればCodexやプラグインの国際化が進んだ昨今、なぜプラグインページだけが英語のみなのか少し疑問です。


最後に、初めてのプラグインで不具合が何度も発生したにもかかわらず、根気強く協力していただいたキャリコさん、ありがとうございました。



現在のページを共有する



現在のページに関連する記事


おすすめの記事


いただいたコメントなど

  1. 黒猫 のコメント:

    Oxyさん、こんにちは。
    プラグイン便利に使わせてもらっています。

    ファイル名「sbs-social-count-cache.php」の1360行目、ツイートボタンのa要素のURL中に、oxynotes.comさんのURLやサイトタイトルの文字列が含まれているような気がします。1423行目のスクエアタイプの方も同じだと思います。ご報告しておきます。

    • oxy のコメント:

      情報ありがとうございます。
      そして失礼しました。バージョン1.3.3で修正しました。

      また何かありましたらよろしくお願いいたします。

  2. 匿名 のコメント:

    ツイートするときの@(サイト名)のところを自分のTwitterのIDに変更することはできますか?

    • oxy のコメント:

      お問い合わせありがとうございます。
      Twitterの表記はカスタマイズできるようにして欲しいという依頼をいくつか頂いているので、
      自由に変更できるようにしようと思います。
      次回のバージョンアップで対応する予定です。

    • 匿名 のコメント:

      ありがとうございます。
      開発頑張ってください応援しています。

  3. 匿名 のコメント:

    スクエアタイプのコードがバルーンタイプのコードと全く同じものになっています。
    修正お願いします

    • oxy のコメント:

      デザインはCSSで変更しています。
      コードが同じだと、具体的にどのような不具合がありますか?

    • 匿名 のコメント:

      わかりにくかったようですみません。
      このページ内のコードがスクエアタイプとバルーンタイプが全く同じになってしまっています。
      という意味です。

      スクエアタイプの正しいコードは

      ではなく

      ですよね?

    • oxy のコメント:

      (コメント欄ではタグが使えないので表示されていないようです)
      おっしゃっている意味がわかりました。
      ご指摘ありがとうございます。修正しました。

  4. 匿名 のコメント:

    管理人様 はじめまして。
    Step by Step Social Count Cacheの導入を検討しております。

    現在、SNS Count Cacheという、同種のSNSキャッシュプラグインを使用しているのですが、
    記事数が多いせいか(2000記事ほど)、1~2日ほど経つとキャッシュされなくなってしまいます。
    作成者様に連絡差し上げたのですが御返事もないため原因もわからず、2日おきくらいにリセットしている状況のところ、
    こちらのプラグインに辿り着きました。

    Step by Step Social Count Cacheの導入にあたって心配なのが、上記のプラグインのようにキャッシュされなくなることです。
    記事数が多いせいでキャッシュされなくなる、といった不具合はございませんでしょうか。

    また、ツイッターのカウント数ですが、公式のAPIは廃止されましたが、有志による代替APIがあるようですが、そちらを使用してのツイッターのカウント数表示にはご対応の予定は御座いませんか。

    御返事いただけると幸いでございます。宜しくお願い致します。

    • oxy のコメント:

      プラグインの導入を検討していただきありがとうございます。
      SNS Count Cacheは5分で10記事ずつCronで定期的にカウントを取得するといった仕組みだったと思います。(具体的なソースは追っていないので巡回頻度は不明)
      そのため、記事数が多いとカウントの反映に時間がかかるのかもしれません。もしくはCronが何らかの原因で停止しているということも考えられます。他にもWordPressのCronはユーザーのアクセスをフラグに動作する擬似Cronなので、アクセスが無いと更新が遅れるということも考えられます。

      このプラグインは導入時のみCronでカウントを取得しますが、基本的にはユーザーがアクセスした時点でカウントを取得します。そのため、おっしゃっているようなカウントが取得できないということは無いはずです。もちろんAPI側に何らかの不具合があれば別です。

      有志による代替APIの使用は、現在このサイトでテスト中です。
      1カ月以上運営して不具合は無いようなので、APIの製作者様に許可がいただければ導入予定です。
      相手もあることなので、いつまでに導入するという確約は今のところできません。

      ご検討、よろしくお願いします。

    • oxy のコメント:

      count.jsoon APIを利用してTwitterのカウントが可能になりました。(APIの作者様に快諾をいただきました。)
      上の解説にも追記しましたが、widgetoon.js & count.jsoonへサイト登録が必要になります。

      良かったら、使用してみてください。

  5. 小塚 のコメント:

    こんばんは。
    プラグインを利用させていただいております。
    Facebookのカウントが0のままなので、「App Token」の認証? が通っているのか判断できたら良いと思いました。
    「App Token」が間違っているのか、それとも他の要因があるのか。
    現状がどのような状態なのか分かれば最高だと思いました!
    Twitterはカウントされているのですが。。。

    宜しくお願い致します。

    • oxy のコメント:

      プラグインのご利用ありがとうございます。
      次のバージョンで認証エラーの表記を追加したいと思います。

  6. とり のコメント:

    はじめまして。
    SNSボタン系プラグインで、バルーン表示ができるのもを探していたところ、素晴らしいプラグインにやっと巡り合うことができました!
    さっそく利用させて頂いたのですが、記事タイトル文字列の中に「#」(半角シャープ)が入っている場合に[[title]]で拾った文字列以降がコメントアウトされてしまいます。
    他のソーシャルボタンプラグインでは「#」を「%23」に置換していたりするので、対応方法について教えていただけないでしょうか?

    • oxy のコメント:

      とりさん、はじめまして。
      プラグインを利用していただきありがとうございます。
      ご要望の件ですが、当然考慮すべきところでしたが、抜け落ちていました。失礼しました。
      修正したものをバージョン1.5.2としてアップロードしました。
      お手数ですが、インストールし直してご利用ください。

  7. ねこ のコメント:

    はじめまして。
    Facebookのカウント数のキャッシュの件で困っていたところに、このプラグインと出会えました。

    通常のWordPressのループ内での使用ではなく、カスタム投稿で登録したエリアに登録したURLに紐付いたカウント数を表示したいのですが、
    URLの指定は出来ますでしょうか?

    お教え頂けたら幸いです。
    よろしくお願いします。

    • oxy のコメント:

      返信遅くなって失礼しました。

      URLをパラメータにしてカウントを取得する方法は用意していません。
      URLに対応するサブループを呼び出し、サブループの中でsbs_get_all()等を使ってください。

  8. みやき のコメント:

    大変ありがたく使わせていただいております!
    一つだけ追加コードを教えてもらいたいのですが、
    もし、カウント数が0の場合は、数字の部分は何も表示されない(空白でもOK)とできますでしょうか?

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

    • oxy のコメント:

      プラグインを利用していただきありがとうございます。
      カウントが0のときに非表示にする方法は複数あると思いますが、わかりやすく以下のような形でどうでしょうか?

      <?php
           $socal_count = sbs_get_all();
           if( ! empty( $socal_count["twitter"] ) ){
                echo $socal_count["twitter"];
           }
      ?>
      
  9. ちば のコメント:

    プラグインの導入を検討させて頂いており、質問が御座います。
    プラグイン利用開始後に記事のURLが変更となった場合も、カウントしたシェア数は引き継がれますでしょうか?
    お忙しいところ恐れ入りますがご教示下さいますと幸いです。

    • oxy のコメント:

      ご検討いただき恐縮です。
      このプラグインは投稿のIDをベースにカウントを収集しています。
      そのためURLが変更になってもシェア数は引き継がれます。

      また、もし上手く行かなかった場合でも、Cronを使って自動で再取得する設定があるので、利用していただければ最新の状態に更新されると思います。

コメントを残す

プログラミングに関する質問は「日本語でプログラミングの悩みを解決するQ&Aサイト sukegra」をご利用ください。面倒な登録なしでご利用になりれます。