PHPでカウント付のSNSシェアボタンを自作してみた

カウント付SNSシェアボタンをPHPで作ってみる

SNSのシェボタンを全部公式のボタンで作るとかなり表示が遅なくなるので、Twitter、Facebook、はてブ、Pocket のSNSシェアボタンを作ることにしました。。シェアされているカウント付で非同期で実行できるJavascriptを使って行いたいところですが、Javascriptを扱う実力がないので、今回はをPHPで実力の範囲内でチャレンジしてみました。

うまくいけばこんなボタンが表示されます

これを表示するPHPとHTMLコード

仮に、AppleのWEBサイト(https://www.apple.com/jp/)をシェアするためのSNSボタンとして記載しています。アイコンはFont AwesomeをCDNから非同期で読み込むようにしています。

<?php
<br>
//カウント数を取得したい対象URL(サンプル)
$url = 'https://www.apple.com/jp/';
<br>
//現在のページで取得したいとき
//$url = 'https://'.$_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
<br>
//Twitter//
function get_twitter_count($url) {
	$url = urlencode($url);
	$ch = curl_init("http://jsoon.digitiminimi.com/twitter/count.json?url=$url");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$json = curl_exec($ch);
	curl_close($ch);
	$array = json_decode($json, true ) ;
	$count = strval($array['count']);
	$count = num_format($count);
	return $count;
	}
<br>
//facebook//
function get_facebook_count($url) {
	$url = urlencode($url);
	$ch = curl_init("https://graph.facebook.com/?id=$url");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$json = curl_exec($ch);
	curl_close($ch);
	$array = json_decode($json, true ) ;
	$count = $array['share']['share_count'];
	$count = num_format($count);
	return $count;
}
<br>
//Hatena
	function get_hatena_count($url) {
	$url = urlencode($url);
	$ch = curl_init("https://b.hatena.ne.jp/entry.count?url=$url");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$count = curl_exec($ch);
	curl_close($ch);
	$count = num_format($count);
	return $count;
}
<br>
//Pocket
	function get_pocket_count($url) {
	$url = urlencode($url);
<br>
	//指定されたURLのPocketボタンを取得
	$ch = curl_init("https://widgets.getpocket.com/v1/button?v=1&count=horizontal&url=$url&src=$url");
	curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
	$html = curl_exec($ch);
	curl_close($ch);
<br>
	//PocketボタンのHTMLソースを読み込みXMLパーサーを作成
	$dom = new DOMDocument('1.0', 'UTF-8');
	$dom->preserveWhiteSpace = false;
	$dom->loadHTML($html);
	$xmlString = $dom->saveXML();
	$xmlObject = simplexml_load_string($xmlString);
<br>
	//XMLをJSONに変換
	$array = json_decode(json_encode($xmlObject), true);
<br>
	//配列からカウント数を文字列として取り出す
	$count = strval($array['body']['div']['a']['span']['em']);
	$count = num_format($count);
	return $count;
}
<br>
function num_format($count) {
	//3桁区切りのカンマを削除
	$count = str_replace(',','',$count);
	//数値に変換
	$count = intval($count);
	// 共有数を表示
	return isset($count) ? intval($count) : 0 ;
}
<br>
	/*
	//カウント数表示(デバッグ用)
	echo $url."<br>\n";
	echo urlencode($url)."<br>\n";
	echo 'Facebook→ '.get_facebook_count($url)."<br>\n"
	echo 'Twitter→ '.get_twitter_count($url)."<br>\n"
	echo 'Hatena→ '.get_hatena_count($url)."<br>\n"
	echo 'Pocket→ '.get_pocket_count($url)."<br>\n"
	*/
<br>
?>
<!DOCTYPE html>
<html lang="ja" itemscope itemtype="http://schema.org/WebPage">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css">
<style>
.snsbtn {
	width: 100%;
	}
<br>
.snsbtn li {
	display: inline-block;
	border-radius: 2px;
	width: 80px;
	padding: 3px;
	margin-left: 3px;
	}
<br>
.snsbtn li span {
	display: inline-block;
	text-align: center;
	width: 70%;
	font-size: 12px;
	font-weight: bold;
	color: #fff;
	}
<br>
.snsbtn li i {
	display: inline-block;
	text-align: center;
	width: 30%;
	color: #fff;
	font-size: 14px;
	position: relative;
	top: 1px;
	}
<br>
.snsbtn .btn-tw {
	background-color: #55ACEE;
	}
<br>
.snsbtn .btn-fb {
	background-color: #3A5795;
	}
<br>
.snsbtn .btn-hb {
	background-color: #008CE1;
	}
<br>
.snsbtn .btn-pk {
	background-color: #ef4357;
	}
<br>
.snsbtn .btn-line {
	background-color: #1dcd00;
	}
<br>
.btn-hb:hover,.btn-tw:hover,.btn-fb:hover,.btn-pk:hover,.btn-line:hover {
	background-color: #ccc;
	}
<br>
i.fa-hatena:before {
	content: "B!";
	font-family: Verdana;
	font-weight: bold;
	}
<br>
</style>
</head>
<body>
<div class="entry-social-buttons clearfix">
<ul class="snsbtn share" title="<?php echo urlencode($url); ?>"><!--
--><li class="btn-tw">
<a href="//twitter.com/intent/tweet?url=<?php echo urlencode($url); ?>" target="_blank">
<i class="fab fa-twitter"></i><span><?php echo get_twitter_count($url); ?></span>
</a>
</li><!--
--><li class="btn-fb">
<a href="//www.facebook.com/sharer/sharer.php?u=<?php echo urlencode($url); ?>" onclick="window.open('https://www.facebook.com/sharer/sharer.php?u=<?php echo urlencode($url); ?>', 'new', 'width=500,height=300');return false;" target="_blank">
<i class="fab fa-facebook-f"></i><span><?php echo get_facebook_count($url); ?></span>
</a>
</li><!--
--><li class="btn-hb">
<a href="//b.hatena.ne.jp/entry/<?php echo urlencode(urlencode($url)); ?>" target="_blank">
<i class="fa fa-hatena"></i><span><?php echo get_hatena_count($url); ?></span>
</a>
</li><!--
--><li class="btn-pk">
<a href="//getpocket.com/edit?url=<?php echo urlencode($url); ?>" target="_blank">
<i class="fab fa-get-pocket"></i><span><?php echo get_pocket_count($url); ?></span>
</a>
</li><!--
--><li class="btn-line">
<a href="//social-plugins.line.me/lineit/share?url=<?php echo urlencode($url); ?>" target="_blank">
<i class="fab fa-line"></i><span>LINE</span>
</a>
</li>
</ul>
</div>
<script>
window.addEventListener("load",function(){ const css=[ "//cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css" ];for(i in css){ let html=document.createElement("link");html.rel="stylesheet";html.href=css[i];html.async=true;document.head.appendChild(html);}});
</script>
</body>
</html>

説明

SNSによってAPIから受け取るカウント数が異なりますが、共通してcURLというのを使って各SNSのカウント数が含まれた情報を取得しています。

TwitterとFacebookはAPIからJSONでデータが戻ってくるので、それをjson_decodeで配列に変換してカウント数の部分を取得しています。

Twitterの公式APIは現在ないのですが、https://jsoon.digitiminimi.com/のAPIから取得できます。APIを使用するためには事前にhttps://jsoon.digitiminimi.com/に登録が必要です。登録しないと値が取得できないのでカウント数が「0」のままになってしまいます。

はてブは数字のみがダイレクトに帰ってくるので簡単です。

Pocketに関してはPocketにストックされたWEBページのカウント数数を取得できるAPIがないので、公式ボタンのHTMLを取得→XMLに変換→JSONに変換→配列に変換し、その中からカウント数を抜き出しています。

GTmetrixで計測してみた

サイトのテストを行えるGTmetrixでスピードテストしてみました。アイコンにFont Awesomeを使っているのと、4つのSNSを同期で順番に作業しているせいでしょうか?

1秒以下を期待していたのですが、何度テストしても約2秒前後かかりました。

公式ボタンに比べたら速いのですが、劇的に速くするためには非同期で実行させる方法を考えないといけないですね。

参考ページ

2019/01/14追記

カウント数の取得を非同期で行うcurl_multi関数を使って少し高速かできたので、以下のページにまとめました。

Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。