PHPでTwitterのOAuth認証するサイトのサンプルページを作ってみました

PHPでTwitterのOAuth認証でログインするサイトのサンプルページを作って見ました。実行内容は、次の通りです。
.htaccess を使ってすべてのアクセスを index.php に渡す。index.php でログイン済みかどうかをチェック。ログインしていない場合、template.php を使って状況に応じたメッセージを表示。「ログイン」をクリックしたら、Twitterの認証ページヘリダイレクト。認証がすんだら page_1.php を開く。あとは自由にページを見られる。存在しないページをリクエストされたら、404.php を表示する。「ログアウト」をクリックしたらログアウトする。

PHPでTwitterのOAuth認証を使ってログインするサイトのサンプルページを作って見ました。
http://php-oauth-sample.dwm.me/

追記:上のはあまりにもみすぼらしいので、ちょっと真面目に作り直しました。こちらが新しいサンプルです。
http://dwm.me/sample/todo/

ただし、今ご覧頂いているページの内容は最初のサンプルにそって書かれています。

作ったファイルは、.htaccess と index.php、page_1.php、page_2.php、404.php、それから template.php です。

ファイルはhttp://php-oauth-sample.dwm.me/twitter_oauth_sample.zip からダウンロードできます。

実行内容は、次の通りです。

  • .htaccess を使ってすべてのアクセスを index.php に渡す。
  • index.php でログイン済みかどうかをチェック。
  • ログインしていない場合、template.php を使って状況に応じたメッセージを表示。
  • 「ログイン」をクリックしたら、Twitterの認証ページヘリダイレクト。
  • 認証がすんだら page_1.php を開く。
  • あとは自由にページを見られる。(他には page_2.php しかありませんけど)
  • 存在しないページをリクエストされたら、404.php を表示する。
  • 「ログアウト」をクリックしたらログアウトする。

page_1.php と page_2.php それから 404.php は独立していて、それ以外の処理を template.php に渡して表示します。

また、ライブラリとして https://github.com/abraham/twitteroauthで公開されている twitteroauth を使っています。(上に書いた圧縮ファイルの http://php-oauth-sample.dwm.me/twitter_oauth_sample.zip には同梱していません)

Twitter Apps で認証キーを取得する

まずはじめにTwitter Apps(https://apps.twitter.com/)で、API key と API secret を取得します。

Twitter AppsTwitter Apps

Website と書かれた項目と Callback URL と書かれた項目以外は、好きに書いて構いませんが、認証画面で次のように表示されます。

Twitter Apps

Website には、認証させるサイトのURLを入力します。

Callback URL は、認証が済んだ後に自動でリダイレクトされる先のURLです。私のサンプルでは http://php-oauth-sample.dwm.me/twitter_callback/ になっていますが、ここで必要なデータを取得したら、再びリダイレクトして http://php-oauth-sample.dwm.me/page_1/ に飛ばしています。結果として、ログインしたユーザーが最初に見るのは http://php-oauth-sample.dwm.me/twitter_callback/ ではなく http://php-oauth-sample.dwm.me/page_1/ になります。

また、Twitter Apps に登録する際に注意しなくてはいけないのが、Allow this application to be used to Sign in with Twitter という部分です。ここにチェックを入れておかないと、ログインする度に認証ページが開いてしまいます。

ここにチェックをいれておけば、最初の認証以外は、すぐに http://php-oauth-sample.dwm.me/twitter_callback/ へリダイレクトさせることが出来ます。その説明は次のページが詳しいです。

PHPで「Sign in with Twitter」を実装する方法 – 頭ん中

同ページより引用

  • ユーザーが呼び出し元アプリケーションを承認している場合
    • ユーザーが Twitter にログインしている場合:直ちに承認されて、呼び出し元のアプリケーション(callback URL)にリダイレクトされる。
    • ユーザーが Twitter にログインしていない場合:Twitter のログイン画面が表示され、ログイン後は直ちに承認されて、呼び出し元のアプリケーションにリダイレクトされる。
  • ユーザーがまだ呼び出し元アプリケーションを承認していない場合、あるいは承認を取り消している場合
    • ユーザーが Twitter にログインしている場合:OAuth の承認画面が表示され、承認後は呼び出し元のアプリケーションにリダイレクトされる。
    • ユーザーが Twitter にログインしていない場合:まず Twitter のログイン画面が表示され、ログイン後に OAuth の承認画面に移り、承認後は呼び出し元のアプリケーションにリダイレクトされる。

ライブラリ twitteroauth の取得

OAuth認証をするために使うライブラリを https://github.com/abraham/twitteroauth から取得します。

開いたページの右側に Download ZIP というボタンがあるので、それをクリックするとダウンロードできます。

twitteroauth

ダウンロードした .zip ファイルを解凍するとファイルがたくさんありますが、必要なのは twitteroauth というフォルダだけです。このフォルダの中に入っている2つのファイル OAuth.phptwitteroauth.php を使います。

.htaccess の作成

この項目は私のやった方法の場合で、OAuth認証と基本的に無関係です。

サイトへの、すべてのリクエストを index.php に渡して、そこで処理するために次の内容の .htaccess を用意しました。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule . index.php [QSA,L,PT]
</IfModule>

実際の .htaccess には他にもいろいろ書いていますが、mod_rewrite に必要なところだけ書き出しています。これで、すべてのアクセスは index.php に渡されるので、そこで処理をします。

URLは http://php-oauth-sample.dwm.me/page_1/ という形式で、この場合だと page_1.php を読み込んで表示するようにします。

index.php の内容

大きく分けると switch 文で、次のように処理を振り分けています。

実際に使っているファイルは http://php-oauth-sample.dwm.me/twitter_oauth_sample.zip からダウンロードできますので、そちらを参照してください。

switch($match[1]){
	// ログインをリクエストされた場合
	case TWITTER_LOGIN:

		// 認証用のtokenを取得

		if(token が取得できたら){
			// Twitter へリダイレクトして終了
			//(認証後、登録したリダイレクトページに返ってくる)
			return;
		}

		// token が取得できなければ、表示するメッセージを用意してbreak
		break;

	// Twitterの認証画面からリダイレクトされてきた場合
	case TWITTER_CALLBACK:

		if(認証されていたら){
			// 送られたデータをセッションに渡し
			// http://php-oauth-sample.dwm.me/page_1/ ヘ リダイレクトして終了
			return;
		}

		// 認証されなていなければ、表示するメッセージを用意してbreak
		break;

	// ログアウトをリクエストされた場合
	case LOGOUT:

		// セッションをクリア

		// ログアウト完了のメッセージを用意してbreak
		break;

	// その他のケース
	default:

		if(指定のページが存在する場合){

			if(ログインしていれば){
				// そのページを表示して終了
				return;
			}

			// ログインしていなければ、ログインを促すメッセージを用意

		}else{
			// ページが存在しなければ 404ページを読み込んで終了
			return;
		}

		// 指定のページが存在するけど、ログインしていない場合はbreak
		break;
}

// ここまでで return していなければ
// template.php に用意したメッセージを埋め込んで表示

header('Content-Type: text/html; charset=UTF-8');
require_once(TEMPLATE_FILE);

ログインをリクエストされた場合

// API key と API secret は https://dev.twitter.com/apps から取得する

define('API_KEY', '*************************');
define('API_SECRET', '**************************************************');

define('LOCATION_BASE', 'http://php-oauth-sample.dwm.me');
define('TWITTER_CALLBACK', 'twitter_callback'); // Twitterからのコールバックページ

/************************************************************************/

// switch文から該当部分のみ抜粋

case TWITTER_LOGIN:

	// token を取得

	$auth = new TwitterOAuth(API_KEY, API_SECRET);
	$url = sprintf('%s/%s/', LOCATION_BASE, TWITTER_CALLBACK);
	$token = $auth->getRequestToken($url);

	// token が取得できたら Twitter へリダイレクトして終了
	//(認証後、登録したリダイレクトページに返ってくる)

	if(isset($token['oauth_token']) && isset($token['oauth_token_secret'])){

		// セッションに登録
		$_SESSION['oauth_token']        = $token['oauth_token'];
		$_SESSION['oauth_token_secret'] = $token['oauth_token_secret'];

		// 2つ目の引数が true だと
		// アプリケーションを承認済みユーザーは即座にcallbackページにリダイレクト
		// 未登録の場合は、承認画面を表示後、承認が終わるとリダイレクトされる
		// ただし、Twitter Apps で
		// Allow this application to be used to Sign in with Twitter
		// にチェックを入れておく事が必要

		$auth_url = $auth->getAuthorizeURL($_SESSION['oauth_token'], true);

		header("Location: " . $auth_url);
		return;

	}

	// token が取得できなければ、表示するメッセージを用意してbreak

	$message = 'エラーが発生しました。恐れ入りますが、もう一度やり直してください。';

	break;

Twitterの認証画面からリダイレクトされてきた場合

case TWITTER_CALLBACK:

	// 認証されていたら
	if(isset($_REQUEST['oauth_verifier']) && ('' != $_REQUEST['oauth_verifier'])){

		$auth = new TwitterOAuth(API_KEY, API_SECRET,
			$_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);

		$access_token = $auth->getAccessToken($_REQUEST['oauth_verifier']);

		$_SESSION['user_id']     = $access_token['user_id'];
		$_SESSION['screen_name'] = $access_token['screen_name'];

		// ログイン後、最初に表示するページヘリダイレクトして終了
		// URLにGETで oauth_token と oauth_verifier が含まれているので
		// それを消すために require でファイルを読むのではなくリダイレクトさせる

		// define('FIRST_PAGE', '/page_1/');

		header('Location: ' . LOCATION_BASE . FIRST_PAGE);
		return;

	}

	// 認証されなければ、表示するメッセージを用意してbreak

	$message = 'ログイン出来ません。Twitterアカウントを確認してください。';

	// 認証されていなければセッションの削除
	session_destroy();
	unset($_SESSION);

	break;

ログアウトをリクエストされた場合

case LOGOUT:

	// ログアウト完了のメッセージを用意

	$message = 'ログアウトしました。';

	// セッションの削除
	session_destroy();
	unset($_SESSION);

	break;

閲覧用のページが指定された場合

default:

	// define('FILE_PATTERN', FILES_PATH . '/files/%s.php');
	// .php ファイルは FILES_PATH/files/ にある

	$path = sprintf(FILE_PATTERN, $match[1]);

	// 指定のページが存在する場合

	if(file_exists($path)){

		// ログインしていれば

		if(isset($_SESSION['user_id'])){

			// そのページを表示して終了

			header('Content-Type: text/html; charset=UTF-8');
			require_once($path);
			return;

		}

		// ログインしていなければ、ログインを促すメッセージを準備

		$message = sprintf('%sをご覧になるにはログインが必要です。', $match[1]);

	}else{ // 指定のページが存在しない場合

		// ページが見つからない404ページを読み込んで終了

		header('HTTP/1.0 404 Not Found');

		$file_404 = sprintf(FILE_PATTERN, PAGE_404);
		require_once($file_404);
		return;

	}

	break;

大体、このような流れで処理しています。

動作はデモページ http://php-oauth-sample.dwm.me/ でご確認ください。

実際のファイルはhttp://php-oauth-sample.dwm.me/twitter_oauth_sample.zip からダウンロードできます。(ライブラリの twitteroauth は同梱していません)

Twitterのつぶやきを記事に埋め込む

これは元々は井戸端ランキングのコメント欄に画像付きで寄せた投稿なんですが、
好評だったのでこちらにも転載します。自分の書いたコメントだから転載もいいでしょう。

きっかけはコメント欄にツイッターのツイートをそのまま埋め込んだところ、
やり方を知りたいということでした。

ツイートをコメント欄に埋め込むことはWordPress以外では難しいと思いますが、
記事には埋め込めます。


“Twitterのつぶやきを記事に埋め込む” の続きを読む

Twitterでつぶやいた商品名をブログに列挙

JavaScriptだけでTwitterでつぶやいた商品アフィリエイトをブログに列挙できます。たとえばこれなんか画像もカスタマーレビューも表示されてブログで下手な宣伝するよりも圧倒的に効果的だと思う訳です。

新ブログ「amazon探検隊!」ではTwitterでつぶやいた商品名を列挙するようにしました。
こんな感じです。もちろん全部アフィリエイトです。

Amazon でチェック!

    たとえばこれなんか画像もカスタマーレビューも表示されてもし見てもらえれば
    ブログで下手な宣伝するよりも圧倒的に効果的だと思う訳です。

    追記:このブログの記事下にも導入してみました。

    以前はPHPを使った処理例を書きましたが、JavaScriptだけでも出来ます。


    “Twitterでつぶやいた商品名をブログに列挙” の続きを読む

    JSONPでTwitter API searchメソッド

    今回もWebService/Twitter/API – わすWikiを参考にさせていただきました。

    先日の記事「Twitter API 愛の劇場のソース」では、Twitterのuser_timelineメソッドをPHPで呼び出し、simplexmlを使って処理しました。

    しかし、記事中に書いてあるようにソースに不備があります。

    書き直すに当たり、次の変更を行ないました。

    1. searchメソッドを使って検索する
    2. PHPを使わず、JavaScriptとJSONPだけで構成する。

    前回のソースは、とりあえずTwitter APIがどんなものか動かしてみるレベルの内容です。
    いいコードとはとてもいえないものでした。今回は使う開発言語を減らすことで、コードがスッキリしました。

    アクセス制限の問題もあります。1時間に150アクセスまでなので、PHPを置いたサーバーからTwitterのサーバーにアクセスするより、JavaScriptを読み込んだ各ブラウザからTwitteのサーバーにアクセスさせる方がIPを分散できます。

    さらに、前回はリレー小説の書き手分user_timelineメソッドを呼び出していました。今回はsearchメソッドで、Twitterのサーバーに問い合わせる回数を減らします。

    search API

    http://search.twitter.com/search.json

    赤字のjsonatomにすると、Atomが返ってきます。

    http://search.twitter.com/search.json?q=検索クエリー&callback=コールバック関数名&result_type=recent&rpp=100&since_id=200851367760363520&page=1

    参考記事:GET送信とは?

    必須パラメーターはqです。
    q=には検索クエリーをURLエンコードして送信します。検索クエリーの書き方は後述します。

    callback=にはJSONPのコールバック関数を指定します。このオプションはatomの時には適用されません。

    result_type=には、欲しい検索結果の種類を指定します。指定できるのは以下の3つ。指定しないとrecentが指定されたものとみなされます。

    result_typeに指定できる値
    recent   「新しい発言」を優先的に検索結果に含める
    popular 「人気の高い発言」を優先的に検索結果に含める
    mixed    「新しい発言」と「人気の高い発言」の両方を適度に検索結果に含める

    rpp=には、一度に取得する検索結果の数を指定します。指定できる最大値は100、未指定だと15になります。

    since_id=は指定したIDより大きなIDのステータスのみ取得するオプションです。検索に指定IDそのものは含まれません。

    page=1ページを rpp 件とみなして取得するページを指定します。最初のページは1です。また、rppとpageで遡れるのは、最大1500件までです。

    他にもたくさんのオプションがあり、WebService/Twitter/API – わすWikiにまとめられています。


    ところが、今回も問題がありました。ある日から1話目が表示されなくなったのです。
    どうも、約10日(1.5週)以上前のつぶやきは検索されないようです。

    また、利用できる検索インデックスについても日数の制限をかけています。現在は、1.5週となっていますが1日のささやきが増加するとこの数字はもっと短くなります。
    Twitter ビジネスユーザー向けブログ » Twitter APIで開発をするために知っておくべきことより

    ということで、またスクリプトを修正することになるのですが、それは別の記事にして、この話を続けます。

    検索クエリーの書き方

    今回の検索クエリはこうなりました。

    from:Tom3suteki OR from:welcome2ourshop -RT つづく

    from:Tom3suteki で、投稿者がTom3sutekiのつぶやきを検索します。

    リレー小説なので、投稿者が2人います。from:Tom3suteki または from:welcome2ourshop という場合は、ORで結びます。

    from:Tom3suteki OR from:welcome2ourshop

    ORは大文字で、前後に半角スペースを入れます。

    検索から除外したい文字列の前には  (ハイフン)をつけます。ハイフンと文字列の間にはスペースを入れずにくっつけます。

    RT とすることでRTを含む文字を除外します。つまり、リツィートの除外を指定したことになります。

    つづくなどと、何もつけない文字列を指定すると、その文字列を含んだツィートを探します。

    つまり「from:Tom3suteki OR from:welcome2ourshop -RT つづく」は、「投稿者がTom3sutekiかwelcome2ourshopでRTを含まず(リツィートを含まず)、つづく という文字列があるツィートを探せ」という意味です。

    これを、URLエンコードした上で、q=に続けて書きます。

    “JSONPでTwitter API searchメソッド” の続きを読む

    Twitter API 愛の劇場のソース

    こないだの記事「Twitterで愛の劇場」のソースです。

    このソースを書くにあたってIBMの記事「Twitter REST API の使い方」を参考にさせていただきました。非常にわかりやすい記事です。

    要はRESTで簡単にTwitterのつぶやきを取りこめるAPIが提供されているということです。

    たとえばブラウザのアドレスバーに「https://twitter.com/statuses/user_timeline.xml?id=Tom3suteki」と打ち込めばそれだけでTom3sutekiのつぶやきデータがXMLで取得できます。

    あとは、取得したそのデータを加工すれば、好きなようにTwitterのつぶやきを表示できるというものです。

    http://twitter.com/statuses/user_timeline.xml?id=Tom3suteki

    取得できるフォーマットはXMLの他にJSON、Atom、RSSがあります。
    青文字のxmljsonにすればJSONが、atomにすればAtomが、rssにすればRSSが取得できます。

    idに呼び出したいTwitterのid(Tomさんの場合@Tom3suteki)を指定すれば、好きな人のつぶやきが見られます。

    ただし、これには制約があって「Twitter ヘルプセンター」によると、1時間に150アクセスまでの制限があって、それを越えると一定時間エラーが帰ってくるようです。

    また、指定しないと一度に得られるつぶやきは20個までしか帰って来ません。
    数を指定したい時は、count=200というように指定します。ただし最大値は200です。

    https://twitter.com/statuses/user_timeline.rss?id=Tom3suteki&count=1
    RSSで1個だけ帰ってくるように指定した場合

    このほかにもたくさんの種類のAPIがあって、「WebService/Twitter/API – わすWiki」というページで日本語訳を作ってくれています。

    最初、IBMのページだけを見て、サクッとPHPでソースを書いて公開したのがリレー小説「Twitterで愛の劇場」ビューワーでした。

    ところが、ある時を境にリレー小説の1人が表示されなくなります。はじめは、まさか1時間で150アクセスあったんだろうか?と考えましたが違いました。

    他のことをつぶやいているうちに最新20の中にリレー小説がなくなったから表示されなかっただけでした。

    以下のソースは、その不備のあるソースです。上に書いた以外にもかなり不備があります。
    現在は改訂版を使っていますが、改訂版のソースは別に公開したいと思います。

    “Twitter API 愛の劇場のソース” の続きを読む