PHP v5.6
Facebook SDK for PHP v4.0
あんまり需要なさそうですが、自分でいいね!したFacebookページのフィードをまとめてみたいなーと思って、いろいろ探ってみました。
RSS登録すればいいんですけど最近RSSあんまり使ってないし、いいね!の方が気楽だしってことで
定期的に実行させるにはcron等を使ってphpを自動実行させ、その中でFacebook APIを実行させるのですが、Facebook APIを実行するにあたってアクセストークンが必要になるので、事前にユーザーにFacebookアプリ認証画面通してユーザー情報にアクセスができるようにしておく必要があります。
大枠の流れ
フロント側
- Facebookアプリを通してユーザー情報にアクセスできるようにする
- 有効期限を延長したアクセストークンを取得してDBへ保存
バッチ側
- 登録したアクセストークンを使っていいね!しているFacebookページ一覧を取得
- それぞれいいね!しているFacebookページのフィードを取得
Facebookアプリを通してユーザー情報にアクセスできるようにする
Facebook SDK for PHP v4.0で「いいね!」をしたFacebookページを取得
http://qiita.com/ykyk1218/items/9c315efbd14f6316318c
上のURLの中でFacebookアプリを通してアクセストークンを取得する方法を記載してあります。
しかーし、ここで問題が、、、
有効期限を延長したアクセストークンを取得してDBへ保存
通常のアクセストークンだとせいぜい1時間ぐらいしか時間がもちません。
そこでアクセストークンの有効期限を延長する必要があります。
有効期限を延長したアクセストークンの取得
Facebook APIで有効期限を延長したアクセストークンを取得するにはgrant_type=fb_exchange_token
というパラメータを付与してあげる必要があります。
Facebook SDK for PHPを使う場合はgetLongLivedSession()
を使う事で取得できます。
FacebookSession::setDefaultApplication(APP_ID, APP_SECRET);
$helper = new FacebookRedirectLoginHelper('<facebook認証をした後の戻り先URL(今回はこのURLに戻ってくることとします)>');
$session = $helper->getSessionFromRedirect();
if($session) {
/* ここで有効期限を延長させてます */
$longSession = $session->getLongLivedSession()
$accessToken = $longSession->getToken();
}
これで有効期限が延長されたアクセストークンが返却されます。
ただ、延長されたといっても60日なので、有効期限が切れたばあいはアプリ側でうまいこと
調整する必要があります。
SDKの中身をちょっと見る
ついでにSDKの中でどんなことしているのか見てみます。
こいつがまず呼ばれる関数の処理
public function getLongLivedSession($appId = null, $appSecret = null)
{
$longLivedAccessToken = $this->accessToken->extend($appId, $appSecret);
return new static($longLivedAccessToken, $this->signedRequest);
}
上記の$this->accessToken->extend
の部分
public function extend($appId = null, $appSecret = null)
{
$params = array(
'grant_type' => 'fb_exchange_token',
'fb_exchange_token' => $this->accessToken,
);
return static::requestAccessToken($params, $appId, $appSecret);
}
こんな感じになっていてfb_exchange_tokenを使っているなーってすぐわかりますね!
MongoDBへアクセストークンを保存
MongoDBのインストール
PHPのMongoDB用ドライバのインストール
$ sudo pecl install mongo
もしくは下記を参考にインストールします
http://andres.jaimes.net/876/setup-mongo-php-module-centos-6/
アクセストークンをDBに保存
$con = new MongoClient();
$db = $con->selectDB(<データベース名>);
$col = $db->createCollection("<コレクション名>");
//どのユーザーかわかるように、FacebookユーザーのIDもついでに保存しておく
$request_me = new FacebookRequest($session, 'GET', '/me');
$response_me = $request_me->execute();
$graphObj = $response_me->getGraphObject();
$userId = $graphObj->getProperty('id');
$data = array(
'member_id' => $userId,
'access_token' => $accessToken
);
$ret = $col->insert($data);
登録したアクセストークンを使っていいね!しているFacebookページ一覧を取得
ここからはバッチ処理のはなし
大枠は
Facebook SDK for PHP v4.0で「いいね!」をしたFacebookページを取得
http://qiita.com/ykyk1218/items/9c315efbd14f6316318c
こちらを見ればわかると思います。
変更点としては下記の通り
$session = new FacebookSession($accessToken);
$request = new FacebookRequest($session, 'GET', '/me/likes');
上記のようにセッションを取得するときにアクセストークを使って取得するようにしましょう。
それぞれいいね!しているFacebookページのフィードを取得
RSSフィードのURLがあるので、それを使ってあげればフィードを取得できます。
ただ、UserAgentを適当なブラウザのものにしないとだめっぽかったので、そこだけ注意ですね。
下記が登録したアクセストークンをMongoDBから取得するところから、Facebookページのフィードを登録するまで処理になります。
<?php
require("vendor/autoload.php");
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\GraphUser;
use Facebook\FacebookRequestException;
use Facebook\FacebookRedirectLoginHelper;
FacebookSession::setDefaultApplication(APP_ID, APP_SECRET);
//各ユーザーのアクセストークンを取得する
$con = new MongoClient();
$db = $con->selectDB(DATABASE);
$col = $db->selectCollection(COLLECTION);
$cursor = $col->find();
foreach($cursor as $obj) {
//アクセストークンをもとにいいね!しているページ一覧を取得する
//アクセストークンの期限が切れている場合はエラー
$accessToken = $obj['access_token'];
$memberId = $obj['member_id'];
$session = new FacebookSession($accessToken);
try {
$session->validate();
$request = new FacebookRequest($session, 'GET', '/me/likes');
$response = $request->execute();
registFacebookPage($db, $response, $memberId);
}catch(FacebookRequestException $fe) {
//アクセストークンの有効期限切れとか不正なアクセストークンの場合
unset($sesssion);
echo $fe->getCode();
echo $fe->getMessage();
exit;
}catch(\Exception $e) {
echo $e->getMessage();
exit;
}
}
function registFacebookPage($db, $response, $memberId) {
//フォーマットをjson形式で取得
$facebookFeedUrl = 'https://www.facebook.com/feeds/page.php?format=json&id=';
$facebookPages = array();
$graphObjList = $response->getGraphObjectList();
foreach($graphObjList as $r) {
$pageId = $r->getProperty('id');
$pageName = $r->getProperty('name');
$url = $facebookFeedUrl . $pageId;
$ch = curl_init($url);
//これやらないと直接表示出力される
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
//UA偽装しないとfacebookから怒られるので適当なブラウザのUAにしておく
curl_setopt($ch, CURLOPT_USERAGENT, 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome');
$jsonFeed = curl_exec($ch);
curl_close($ch);
$feeds = json_decode($jsonFeed, true);
$facebookPages[$pageId]['pageName'] = $pageName;
$facebookPages[$pageId]['entries'] = $feeds['entries'];
//mongodbに登録
$colFeeds = $db->createCollection("feeds");
foreach($feeds['entries'] as $entry) {
$dataFeed = array(
"member_id" => $memberId,
"page_id" => $pageId,
"page_name" => $pageName,
"title" => $entry['title'],
"feed_id" => $entry['id'],
"alternate" => $entry['alternate'],
"categories"=> $entry['categories'],
"published" => $entry['published'],
"updated" => $entry['updated'],
"author" => $entry['author'],
"verb" => $entry['verb'],
"objects" => $entry['objects'],
"comments" => $entry['comments'],
"likes" => $entry['likes'],
"content" => $entry['content']
);
//同じidの場合は登録しない
$retCount = $colFeeds->find(array("feed_id" => $dataFeed['feed_id']))->count();
if($retCount > 0) {
//登録済み
continue;
}
$ret = $colFeeds->insert($dataFeed);
if($ret['OK'] != 1) {
//登録エラー
}
}
}
}
?>
あとはこのphpを定期的に実行してあげれば登録されていきます。
やっほー!