FuelPHPでFacebook SDK for PHP v5を使う

FuelPHP(ver.1.7)を使ってちょっとしたモノを作っている。
ログインの仕組みにTwitterとFacebookのOAuthを使いたくて、インプリメント。

Twitterではabraham/twitteroauthを使ってて、安定の「楽で確実なインプリメント」を実施。

FBでは、公式のSDK for PHPを使うわけだけど、いつの間にかv5.0.0になっていた。
v3からv4の時も、かなり仕様が変わっててリファクタリングを余儀なくされたので、v5でも。。。と思っていたら案の定であった。
まあ、それでも「使わせてもらう側」としては文句をいわずに対応。

まずはcomposer.jsonに以下を追加して、composer.phar update。

"facebook/php-sdk-v4" : "~5.0"

こんなコントローラを作成

use Facebook\Facebook;
class Controller_Auth_Fb extends Controller
{
    public function action_request()
    {
        $fb = new Facebook([
            'app_id' => Config::get('app.sns.facebook.app_id'),
            'app_secret' => Config::get('app.sns.facebook.app_secret'),
            'default_graph_version' => 'v2.4',
            'persistent_data_handler' => new MyFbPersistentDataHandler(),
        ]);
        $helper = $fb->getRedirectLoginHelper();
        $url = $helper->getLoginUrl(Config::get('base_url').'auth/fb/');
        Response::redirect($url);
    }

    public function action_index()
    {
        $fb = new Facebook([
            'app_id' => Config::get('app.sns.facebook.app_id'),
            'app_secret' => Config::get('app.sns.facebook.app_secret'),
            'default_graph_version' => 'v2.4',
            'persistent_data_handler' => new MyFbPersistentDataHandler(),
        ]);
        $helper = $fb->getRedirectLoginHelper();
        try {
            $accessToken = $helper->getAccessToken();
            if(!isset($accessToken)) {
                throw new Exception();
            }
            Log::debug(print_r($accessToken,true));

            $client = $fb->getOAuth2Client();
            if(!$accessToken->isLongLived()) {
                $accessToken = $client->getLongLivedAccessToken($accessToken);
            }
            Log::error(print_r($accessToken,true));

            $response = $fb->get('/me',$accessToken);
            $data = $response->getGraphObject()->asArray();
            $data['token'] = (string)$accessToken;
            Log::error(print_r($data,true));

        } catch(Exception $e) {
            Log::error($e->getMessage());
            Session::set_flash('msg', "danger:Faild to login with facebook...");
        }

        Response::redirect(Uri::base(false));
    }
}

action_request()でログイン用URLを生成し、そこにredirect(ページ上のログインリンクはauth/fb/request/を張っとく。事前にログインURL取得してページにそれを晒してもいいのだけどこちらを選択)。

action_index()は、FBからのコールバック受け取り用メソッド。
action_request()でのgetLoginUrl()呼び出し時に指定してる。

問題は、action_request()/action_index()どちらでも生成しているFacebookオブジェクト。
ここでconfigデータで’persistent_data_handler’としてMyFbPersistentDataHandlerオブジェクトを渡している。

これ、デフォルト(configで指定しなければ)ではPHPのsessionが使われる(session_start()とかのアレね)。
でも、FuelPHPのセッションクラスでは、PHPのsessionを偽装してインプリメントされている。
よって、Facebookオブジェクトをデフォルトで生成し使おうとすると、「Sessions are not active. Please make sure session_start() is at the top of your script.」なんて例外が投げられる。
v3とかv4では、session_startしてるかどうかはチェックされてなかったので、FuelPHPの偽装でも動いてた。
v5では、チェックするようになったみたい。

こんな例外が投げられたからといって、session_start()してもダメ。
FuelPHPのセッションクラスと整合性が保てない。

そこで、自身でPersistentDataHandlerを用意してあげなくてはいけない。

use Facebook\PersistentData\PersistentDataInterface;

class MyFbPersistentDataHandler implements PersistentDataInterface
{
    public function __construct() {
        Session::instance();
    }

    public function get($key) {
        return Session::get($key);
    }

    public function set($key, $value) {
        Session::set($key,$value);
    }
}

こんな具合にPersistentDataInterfaceをインプリメントしてあげる。
これをPersistent Data Handlerとして使うことで、FuelPHPでもSDK for PHP v5を使えるようになる。
ちゃんと、Long Lived Tokenもゲットできる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です