JavaScriptでお手軽にFacebookのアプリを作る

 前々から書こう書こうと思っていた、FacebookのJavaScriptSDKの解説エントリーです。
 APIや規格、HipHopやliftといったオープンソースなどの陰に隠れがちですが、このJavaScriptSDKもなかなか面白いです。

3行で解るJavaScript SDK

  1. 投稿・認証・署名を含めた全APIアクセスをサポート
  2. 公式なUIもついてくる
  3. Facebookアプリも、外部のマッシュアップサイトもこれ一つでOK

 つまり、これ一つで簡単なクライアント機能をもったサイトまたはFacebookアプリが作れちゃいます。
 情報を取ってきてなにか書いてもらって投稿するのはもちろん、ちょっとしたクローリングをおまけにつけたアプリまでJavaScriptの範囲内で完結しますので、サーバー側で凝った処理を実装するのではなく、JavaScript側で可能な限り完結させるのがベストプラクティスといえます。

とりあえず試す

 GoogleのAjaxCodePlayGroundと同じように、Facebookにも公式のテストページがあります。横のログ表示部分で返り値も確認できるので便利です。
 基本的に、ここでのテストを前提に話を進めていきます。とりあえず下のサンプルリンクからいくつか試してなんとなくでいいので感じを掴んでみてください。 

 インストールして試したい場合はこちらのエントリーが参考になります。Facebookアプリ前提ですか、前述のように普通のSDKでも同じです

 だだし、以下の2点に注意が必要です。

 投稿をしたい場合、認証が必要になりますので、ローカルでテストしたい場合はアプリケーションの個別ページ→設定を編集→Web SiteにあるサイトURLをテスト用サーバーのURL(たいていはhttp://localhost/。最後の/が必要なので、ポート番号をつける場合は注意してください)に設定しておく必要があります。
 前述の通りこれはFacebookアプリとして動作させる場合も同様です。また、アプリのページをiframeに設定しておけばFacebookアプリの見た目のテストもローカルにおいたまま出来ます。なので、公開用とは別にテスト用のアカウントを取得しておくといいでしょう。

 また、リンク先で例示されているHTMLのbody直下にある、idがfb-rootの空のdivはFacebookの独自タグであるFBMLを操作するのに必要です。意外とこれは内部的にも使われているので、消さないでください。

まずはログイン

 FacebookAPIを使うのにまず大事なのはログインです。これは非常に簡単でFB.loginというAPIを叩くだけです

FB.getLoginStatus(function(response) {
	if (response.session) {
	    //ログイン後の処理
	} else {
	   login()//ログインしてないのでログインしてもらう
	}
});
function login(){
	FB.login(function(response) {
	  if (response.session) {
	    if (response.perms) {
	      //ログイン後の処理
	    } else {
	      //パーミッション不許可。土下座しなくちゃダメですか(><)
	    }
	  } else {
	    // ログイン失敗
	  }
	}, {perms:'read_stream,publish_stream,offline_access'});
}


 重要なのは引数の二番目のパーミッションの指定で、Facebookでは情報取得についてかなり細かく許可するかしないかが分かれています。詳しい内容はPermissionsを見てください。
 また、パーミショションの指定は許可内容を表す文字列をカンマでつないだ文字列となります。

FB.apiを攻略しよう(Graph API編)

 いくつかサンプル使ってみると、APIを叩くような基本的な操作はFB.apiという関数一本でまかなわれているのが解ると思います。
 このFB.apiは最初の引数の型によって操作するAPIとURLが異なります
 
 引数は最低二つ、最大で四つです。
 

 最初の引数が文字列の場合、FB.apiはこれをurlとして解釈しGraph APIを操作します。また、二つ目の引数に連想配列を指定した場合、これをクエリのパラメーターとして解釈します。
 urlはGraph APIのドキュメントにあるアドレスからhttps://graph.facebook.comを除いたものになりますので、例えば「test」という単語で検索する場合は

    FB.api('/search',{q:'test'},your_callback);

 また、2番目の引数が文字列の場合、それをリクエストメソッドとして解釈しようとします。この場合、3番目の引数が連想配列ならばクエリパラメーターになり、4番目がコールバック関数となります
 つまり、ウォールに投稿したい場合は

 FB.api(
    '/me/feed',
    'post',
    { message: 'サンプル' },
    your_callback
  );

となります。

以下はBret Taylorさんの情報を表示するサンプルです

<fb:login-button perms="email"></fb:login-button>
<div id="me"></div>

<script>

  div    = document.getElementById('me'),
  showMe = function(response) {
    if (!response.session) {
      div.innerHTML = '<em>Not Connected</em>';
    } else {
      FB.api('/btaylor', function(response) {
        var html = '<table>';
        for (var key in response) {
          html += (
            '<tr>' +
              '<th>' + key + '</th>' +
              '<td>' + response[key] + '</td>' +
            '</tr>'
          );
        }
        div.innerHTML = html;
      });
    }
  };
FB.getLoginStatus(function(response) {
  showMe(response);
  FB.Event.subscribe('auth.sessionChange', showMe);
});
</script>

FB.apiを攻略しよう(FQL編)

 最初の引数に連想配列が与えられた場合、FB.apiはmethodに設定された値を元にhttps://api.facebook.com/method/の下にあるアドレスにアクセスしようとします。
 このURLの下にあるのはSQLライクな文法でFacebookのデータを検索できるAPIであるFQLです。

 例えばID4番さんの名前を表示する場合は以下のような書き方になります
 

User ID 4 is <strong id="name">?</strong>.

<script>
FB.api(
  {
    method: 'fql.query',
    query: 'SELECT name FROM user WHERE uid=4'
  },
  function(response) {
    Log.info('API Callback', response);
    document.getElementById('name').innerHTML =response[0].name;
  }
);
</script>

 実際には、FQLはFB.Data.queryという関数があり、そちらを使った方が色々と便利です。
 前述のコードを書き直すとこのようになります。

User ID 4 is <strong id="name">?</strong>.

<script>
var user_id=4
var query = FB.Data.query('select name, uid from user where uid={0}',
                           user_id);
 query.wait(function(rows) {
   document.getElementById('name').innerHTML ='Your name is ' + rows[0].name;
 });
</script>

 このようにサーバーサイドスクリプトでおなじみの変数バインディングや、サブリクエリのサポート、複数のクエリを同時に投げてその結果を待つFB.Data.waitなどなかなか面白い機能があります…が、肝心のFQLが意外と使えません。
 インデックスされている範囲が痒いところに手が届かないというか。サブクエリもできるのですがありえないレベルで重く、お世辞にも実用的とは言いがたいです。
 ただ、たまにGraph APIで取れない情報が取れたりすることもありますし、一応、期間を限った検索はFQLの方が得意ですので、もしGraphAPIでダメそうならばドキュメントに目を通しておくといいでしょう。
 

FBアプリを作りませんか?

 こんな風に、FacebookはJavaScriptSDKとHTMLを使うと手軽にアプリケーションを作る事ができます。
 情報を取ってきてFacebookに投稿するだけのアプリであれば、多分一日くらいで出来るでしょう。空いている時間にFacebookを使ったマッシュアップアプリを作ってみてはいかがでしょうか?