2011年2月26日土曜日

CakePHPでFacebookにConnectしてみた

日本でも着実にユーザーを増やしているFacebook。いいねボタンが色んなサイトに設置されていますし、某CGMサイトでは自身のコメントシステムを排除してFacebookプラグインに置き換えたり(それまで投稿されたコメント見れなくなった…)と勢いがハンパないです。

そんな激アツなFacebookとCakePHPを連携してアカウントを作成するコントローラーを作成してみました。


  1. まずはオフィシャルのphp-sdkを入手
  2. ゲットしたファイル群をapp/vendorsにfacebookディレクトリを作って丸ごとぶち込む
  3. FacebookControllerを作成(ユーザ情報のテーブルを扱えるならなんでもいい)
さてここからコーディング開始。
まずはメンバ変数$facebookを宣言して、beforeFilter()でインスタンスを生成します。
var $facebook;

function beforeFilter(){
  
    App::import('Vendor', 'facebook/src/facebook');
    $this->facebook = new Facebook(array(
        'appId'  => '123456789123456789',
        'secret' => '123456abcdefghijklmnopqrstuvwxyz',
        'cookie' => true,
    ));
  
}
appIdとsecretは自分で登録したアプリの情報に置き換えてください。
php-sdkのexampleではFBMLとJavascriptを使ってログインボタンを生成してますが、今回は純粋にFacebookController::index()にアクセスしたらFacebookに飛ばされて初回だけ承認する流れにします。
なぜならphp以外の記述がめんどくさいからです!

では以下のようにindex()を用意します。
function index(){
  
    $this->autoRender = false;
  
    $url = $this->facebook->getLoginUrl(array('next' => 'http://localhost/facebook/callback', 'req_perms' => 'email,publish_stream'));
    $this->redirect($url);
 
}
ここで重要なのが$autoRenderにfalseを代入しとかないとリダイレクトしてくれません。ちょっとハマりました。
でgetLoginUrl()メソッドでurlを生成するんですが、引数の連想配列に'req_perms'というキーでアプリからアクセス出来るapiを選べるんです。ユーザ登録に使うのでemailと、あとウォールへ書き込み出来るようにpublish_streamも入れています。ここのページでいろんなapiが確認出来ますよ->Permissions - Facebook開発者

でさらにcallback()を用意します。
function callback(){
 
    $session = $this->facebook->getSession();
    $me = null;
  
    if ($session) {
        try {
            $uid = $this->facebook->getUser();
            $me = $this->facebook->api('/me');
        } catch (FacebookApiException $e) {
            error_log($e);
        }
    }
    $access_token = $this->facebook->getAccessToken();
    $user_data = array(
        'User' => array(
            'username' => $me['first_name'].'.'.$me['last_name'],
            'password' => $this->Auth->password(mt_rand()),
            'email' => $me['email'],
            'other_service_id' => array('facebook' => $me['id'], 'token' => $access_token)
        )
    );
}
承認して戻って来たユーザの$sessionをとって確認して、api('/me')でユーザ情報の部分を叩けば名前とか、性別、言語等がゲット出来ます。ちなみにgetLoginUrl()のreq_permsで指定したemailも$meの中に入ってるんでpr($me)してみるといいと思います。
ここまでできたら$data['User']作成してユーザ登録、ログイン処理という感じなんですがaccessTokenも一緒にDBに保存しておけば以下のコードでウォールへの投稿もできましたよ。

$attachment =  array(
    'access_token' => $access_token,
    'message' => "This is test.",
    'name' => "name test",
    'link' => "http://testtesttesttesttest.com",
    'description' => "here description",
    'picture'=> "http://example.jp/image.jpg"
);
$this->facebook->api('/me/feed', 'POST', $attachment);

こんなかんじで簡単にFacebbokConnectをCakePHPで使えました。
2011年2月15日火曜日

CakePHP viewにelementを埋め込む

WordPressではサイドバーを共通化する場合は(というかブログだから当然サイドバーは共通ですよね)
get_sidebar();

//もしくは定義済みの定数と組み合わせて

include TEMPLATEPATH . '/header2.php';

とか書いたりしますが、CakePHPではどうやるんだろう?とおもってググッてみたら出てきた。
CakePHP View::element() | パン好きのエンジニア
ちょっと違うけど、”View::element()”というメソッドがあった。
Viewの中の一部をelementとして切り出すらしい。

viewフォルダの中を見てみたら確かに /view/element/ というディレクトリがあった。
試しにview内で echo $this->element(); としてみたら読み込むじゃないかァァ
まさに期待通り。

で、データも渡したいなぁと思ってマニュアル見たら
element(string $elementPath, array $data, bool $loadHelpers)
お、二番目に array $data がある。CakePHP的に考えれば、こうゆうときは array('変数名' => '中身') でしょう。と思って試してみたらこれも期待通り!こんな感じでview.ctpからelement.ctpに渡せる
$this->element('sidebar', array('hoge' => 'Hello!'));
もちろんcontrollerでsetした値もそのまま使えるし、繰り返しHTMLパターンがあるなら管理しやすい……と、ここまで書いてて、よく見たら詳しく日本語化されたマニュアルを発見!
http://book.cakephp.org/ja/view/97/Elements
おお!キャッシュも使えるのか♪至れり尽くせりだな。