OAuth認証でTwitterを利用するWebアプリケーション(PHP PECL/oauthの場合)

以前、OAuth認証でTwitterを利用するWebアプリケーション(PHP twitteroauthの場合)をいう記事を書いたのですが、状況がいろいろ変わってきたので、PECL/oauthを使う方法を紹介します。

TwitterのAPIが変わっても、Twitter専用ライブラリがそれに対応するとは限らないので、汎用のOAuthライブラリを使っておいた方がいいかもしれない、という話です。

PECL/oauthを導入してから先に進んでください(参考:PECL/oauthの導入方法)。

アプリの登録

Twitterにアプリを登録し、Consumer KeyとConsumer Secretを取得します。

アプリを一度許可したユーザが確認画面をスキップできるように、つまり「oauth/authorize」ではなく「oauth/authenticate」を使いたい場合は、下のように、「Allow this applicetion…」を有効にしてください。

OAuth認証してつぶやく

3つのファイルに分けて説明します(RSSリーダーではコードが表示されないかもしれません)。

  1. twitter-oauth-start.php: OAuth認証開始
  2. twitter-oauth-end.php: OAuth認証完了
  3. twitter-oauth-post.php: つぶやき投稿

あとで1つのファイルにまとめます。

OAuth認証開始(twitter-oauth-start.php)

「Consumer Key」と「Consumer Secret」、callbackUrlは環境に合わせて書き換えてください。

実験時には、「$oauth->disableSSLChecks();」としておいてもいいでしょう。XAMPPでは、何もしないと「Peer certificate cannot be authenticated with given CA certificates」というエラーになります。Ubuntuでは、自動的に「/etc/ssl/certs/ca-certificates.crt」が読み込まれます。

OAuth認証完了(twitter-oauth-end.php)

つぶやき投稿(twitter-oauth-post.php)

ログアウト

ブラウザを再起動すればはじめに戻りますが、次のようなtwitter-oauth-logout.phpを作っておいてもいいでしょう。

1つのファイルでつぶやく

OAuth認証をしてつぶやく処理を1つのファイルにまとめると次のようになります。

PECL/oauthの導入方法

PHPでOAuth認証をするクライアントを実装するための最も標準的な方法であるはずの、PECL/oauthの導入方法を紹介します。

Ubuntuの場合

まず、以下のコマンドで必要なパッケージをインストールします。

sudo apt-get install apache2 php5 php5-dev php-pear libpcre3-dev make
sudo pecl install oauth

次に、/etc/php5/apache2/php.iniに「extension=oauth.so」を追記し、Apacheを再起動します。

phpinfo()の結果に「OAuth」があれば準備完了です。

Windows(XAMPP)の場合

  1. http://windows.php.net/downloads/pecl/releases/oauth/からバイナリ(XAMPP 1.8.1ならphp_oauth-1.2.3-5.4-ts-vc9-x86.zip)をダウンロード・展開して、php_oauth.dllc:/xampp/php/extにコピーする。
  2. c:/xampp/php/php.iniに「extension=php_oauth.dll」を追記する。
  3. Apacheを再起動する。
  4. phpinfo()の結果に「OAuth」があることを確認する。

Mac OS X

「mac pecl oauth」でググればいいかと思います。

このあたりの詳細については、拙著『Webアプリケーション』などを参照してください。

Twitter APIのパブリックタイムラインが亡くなっていました

拙著『Webアプリケーション構築入門(第2版)』の5.3節「Twitter API」は、以下のような構成になっています。

  • XMLの処理(Java)
  • JSONの処理
    • PHP
    • JavaScript
  • コラム:JSONP

Twitter APIの大部分は、OAuthと呼ばれる認証が必要なのですが、この節の目的はHTTP通信でよく使われるXML形式とJSON形式のデータの処理方法を紹介することだったので、認証の不要なパブリックタイムライン https://dev.twitter.com/docs/api/1/get/statuses/public_timeline を採用していました。

教育的には便利なこのAPIが、先日廃止されてしまったため、5.3節のほとんどのコードが動かなくなっていました。ほとんどすべてのサンプルが動く形で提供されていることを一つのウリにしている書籍で、これはいけません。

というわけで、JSON処理の部分だけ,動くように修正しました。(XML処理の部分はあきらめます。)

https://github.com/taroyabuki/webbook2/tree/master/src/05

第三者のWeb APIを書籍で使うリスクについて、お伝えしました。

『Webアプリケーション構築入門』の郵便番号検索システムをAppFog上で動かす方法

ウェブアプリ構築の入門書である拙著『Webアプリケーション構築入門 第2版』のゴールは、Google Mapsを活用する郵便番号検索システムです。サーバ・サイドのプログラミング言語はJavaとPHPのうち、好きな方を選んで読み進められるようになっています。

ウェブアプリを構築できるようになると、こんどはそれを公開したくなるわけですが、本書の想定読者には学生も入っているので、「まずサーバを用意して・・・」のようなコストのかかる方法ではなく、基本無料の公開方法が必要です。

Java版をHerokuで公開する方法と、PHP版をPHP Fogで公開する方法を以前紹介したのですが、PHP Fogが今年いっぱいでサービスを終了し、AppFogに移行するらしいので、それにあわせてAppFogを試します。

PHP Fogでは、無料では機能が不十分なMySQLを避けてSQLiteを使いましたが、AppFogのMySQLは容量が100MBあるので、郵便番号検索のためには十分です(逆にSQLiteは使えなくなりました。使えれば、移植作業は楽だったのですが)。(参考:AppFog Pricing

作業は以下の通りです。(Ubuntu 12.10 Desktopで動作を確認しました。)

1. AppFogのアカウントを作る。

2. コマンドラインツールをインストールする。(参考:AF Command Line Tool)

sudo apt-get install ruby
sudo gem install af

3. ログインする。

af login

4. アプリを作成し、そこにMySQLサービスを追加、バインドする(ここ、かなり説明を端折っています)。

af bind-service {サービス名} {アプリ名}

5. データベースを準備する。

sudo apt-get install ruby-dev g++ mysql-client libssl-dev
sudo gem install caldecott
sudo gem install eventmachine -- --with-openssl-dir=/usr/lib/ssl
af tunnel

指示に従うとmysqlコマンドで接続できるようになります。あらかじめmysqldumpでデータベースをバックアップしておいて、以下のようなコマンドで復元します。

mysql> source {ファイル名}

6. ソースコードをアップロードする。

cd {コードのあるディレクトリ}
af update {アプリ名}

AppFogの流儀にあわせて、MySQLに接続する部分のコードを次のように書き換えておく必要があります(PHPのバージョンが比較的新しいので、接続時に文字コードを設定できます)。(参考:AppFog Docs MySQL)

//データベースに接続
$services_json = json_decode(getenv("VCAP_SERVICES"),true);
$mysql_config = $services_json["mysql-5.1"][0]["credentials"];
$user = $mysql_config["username"];
$pass = $mysql_config["password"];
$host = $mysql_config["hostname"];
$port = $mysql_config["port"];
$dbname = $mysql_config["name"];
$db = new PDO("mysql:host=$host;port=$port;dbname=$dbname;charset=utf8", $user, $pass);

実行結果は下のようになります。

『Webアプリケーション構築入門』の郵便番号検索システムをPHP Fog上で動かす方法

追記:PHP Fogは2012年12月にサービスを終了するそうなので、後継サービスであるAppFogを試しました。→『Webアプリケーション構築入門』の郵便番号検索システムをAppFog上で動かす方法

ウェブアプリ構築の入門書である拙著『Webアプリケーション構築入門 第2版』のゴールは、Google Mapsを活用する郵便番号検索システムです。サーバ・サイドのプログラミング言語はJavaとPHPのうち、好きな方を選んで読み進められるようになっています。

作成したウェブアプリを公開する方法は人によってさまざまでしょうが、PaaSの無料プランを使うのは魅力的な選択肢です。

Javaで作成したウェブアプリをHerokuというPaaSの上で動かす方法を以前紹介しました。(参照:『Webアプリケーション構築入門』のデータベースアプリケーションをHeroku上で動かす方法

ここでは、PHPで作成したウェブアプリをPHP FogというPaaSの上で動かす方法を紹介します。

手順は次のようになります(1と2は、PHP Fogを使い始めるときに1回だけやればOKです)。詳しくは、Jumpstartsあたりを参照してください。

  1. PHP Fogのアカウントを作る
  2. SSH鍵ファイルを登録する
  3. アプリを作る
  4. データベースを作る
  5. git clone URL
  6. アプリを作る
  7. git add .
  8. git commit -m 'コメント'
  9. git push

PHP FogではMySQLが使えますが、そのアクセス方法は、拙著で説明したのとは少し違っています。データベースへの接続情報は、環境変数に格納されているので、それを参照しながら接続します。参考までに、データベースに接続するためのコードを書くと、次のようになります。p. 149に掲載されているコードと比較してください。

//データベースに接続
$server = getenv('MYSQL_DB_HOST');
$username = getenv('MYSQL_USERNAME');
$password = getenv('MYSQL_PASSWORD');
$dbname=getenv('MYSQL_DB_NAME');

$db = new PDO("mysql:host=$server;dbname=$dbname", $username, $password,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));

しかし、ここではこのコードは使いません。郵便番号データベースを構築するのが面倒だからです。拙著で紹介したように、テーブルを作成して郵便番号データのCSVファイルをインポートすれば郵便番号データベースを構築できるのですが、郵便番号データベースのためのCSVファイルは比較的大きいため、phpMyAdminでインポートしようとするとタイムアウトしてしまうのです。無料で利用できるデータベースサイズが5MBというのもいまいちです。Herokuのときもそうでしたが、無料の範囲内で遊ぼうとすると、データベース周りがいろいろ面倒です。

タイムアウトしてしまうという問題は、「split -C 500K /tmp/zip.csv」などとして分割し、「for f in x*; do mv $f $f.csv; done」として拡張子.csvを付けて、一つずつインポートすれば回避できますが、とても面倒です(Railsに行くのはここではがまんしましょう)。

こんなところで苦労するのはいやなので、Herokuの場合と同様に、SQLiteを組み込んで使うことにします。

ローカルでの実験のために、PHPからSQLiteを使えるようにしておきましょう。

sudo apt-get install php5-sqlite
sudo service apache2 restart

データベースファイル(mydb.sqlite)の作り方はHerokuの場合と同じなので省略します(完成したファイルはここにあります)。このファイルを、zips.phpと同じディレクトリに保存します(接続時にパスを指定するなら、別のディレクトリでもかまいません)。

zips.php内のデータベースに接続する部分を次のように修正します。

//データベースに接続
$db = new PDO('sqlite:mydb.sqlite');

Ajaxによって1文字入力するごとに検索結果を更新するようにしたものは、拙著の中では割愛しましたが(Java版とほとんど同じため)、サポートサイトでは掲載しているので参考にしてください。

実行結果は下のようになります。