Web プロジェクトのための単純な JSON コントローラーを作成する

どのデータベース・バックエンドがプロジェクトに使われるかに関わらず、JSON (JavaScript Object Notation) コントローラーによって開発作業を単純化することができます。至って基本的な JSON コントローラーをセットアップし、皆さんの次期開発プロジェクトを機能強化しましょう。

Thomas Myer, Consultant, Triple Dog Dare Media

Thomas MyerThomas Myer はテキサス州オースティンを拠点に活動するコンサルタントであり、著作者であり、講演者です。彼は Triple Dog Dare Media を運営しており、また Twitter では @myerman としてツイートしています。



2010年 8月 10日

皆さんの次期 PHP/MySQL プロジェクトは、皆さんが最近行った十数件のプロジェクトと似ているかもしれません。つまりそのプロジェクトでも、MySQL データベースを設定し、HTML を含む PHP のビューを作成し、必要に応じて JavaScript コードと CSS ファイルを追加し、データベースに接続し、データベースから情報を抽出してビューに追加し、等々の作業を行うかもしれません。Web 開発に慣れている人であれば、特定の機能を持つコードを分離することによるメリットを理解しているはずです。例えば、SQL クエリーをそのまま直接ビューの中に入れることは避けるべきであり、またデータベースからデータを抽出する関数およびクラスの中には HTML タグを混在させてはなりません。

よく使われる頭字語

  • Ajax: Asynchronous JavaScript + XML
  • CSS: Cascading Style Sheet
  • CSV: Comma-Separated Values
  • HTML: HyperText Markup Language
  • HTTP: HyperText Transfer Protocol
  • JSON: JavaScript Object Notation
  • REST: Representational State Transfer
  • SQL: Structured Query Language
  • XML: Extensible Markup Language

しかしある時点で、皆さんのプロジェクトは PHP/MySQL に通常適したレベルを超えて拡張されるかもしれません。例えばそのプロジェクトには、データベースからのデータを必要とする通常の Web ビューの他に、同じデータベースのデータにアクセスする外部アプリケーション (Facebook など) やモバイル機器 (スマートフォンなど) さえも含まれるようになるかもしれません。

場合によると、データベースの変更または要求により、何らかのフラット・ファイルによる XML リポジトリーを扱わなければならないことがあります。そのような状況では、盲目的に MySQL に頼ってもプロジェクトを完成させることができないかもしれません。

そこで、RESTful な JSON コントローラーをプロジェクトに導入し、仮想的な「交通整理の警察官」として使うことを考えてみてください。この「交通整理の警察官」がデータ・ソースにリクエストを送信し、データ・ソースからのレスポンスを受け取るのです。この記事では REST と JSON の基礎について説明し、RESTful な JSON コントローラーをセットアップする 1 つの方法を示します。その方法は、標準化されたフォーマットでソースからデータを取得できる簡単な方法であり、取得したデータを PHP コードまたは JavaScript コードを使って容易に構文解析することができます。

REST とは何か

典型的な REST アーキテクチャーでは、クライアントがサーバーにリクエストを送信すると、要求されたリソースの表現がレスポンスとして返ってきます。リソースとしては、ほとんどどんな情報オブジェクトの形 (データベースや文書など) をとることも可能であり、またリソースの表現は通常、フォーマット設定された文書 (多くの場合は XML または JSON) であり、リソースの現在の状態または要求された状態のスナップショットとして機能します。

REST のリソースは通常、意味のある URL によって特定され、この URL はさまざまなリクエストの「動詞」(GETPOSTPUTDELETE) を受け付けます。これらの動詞は、多くの開発者におなじみの、CRUD (Create、Retrieve、Update、Delete) モデルといくらか似ています。

例えば、データを取得する (Retrieve) 必要がある場合には GET リクエストを使用し、データを作成 (Create) したい場合には POST リクエストを使用し、データを更新 (Update) したい場合には PUT リクエストを使用し、データを削除 (Delete) したい場合には DELETE リクエストを使用します。

もう 1 つ考慮すべき重要な要素は、レスポンスです。RESTful なサービスでは通常、レスポンスの中に意味のあるコンポーネントとして、レスポンスの本体そのものとステータス・コードが含まれています。実際、多くの REST サーバーでは、ユーザーがレスポンスのフォーマットを指定することができ (XML、CSV、シリアライズされた PHP、プレーン・テキストなど)、そのためにはレスポンスのフォーマットを ACCEPT パラメーターに入れて送信するか、あるいはファイルの拡張子を指定します (/api/users.xml や /api/users.json など)。一方、この記事で実装しようとしている類の REST サーバーでは、レスポンス・フォーマットがハードコーディングされています。ドキュメント化されてさえいれば、そうしたレスポンス・フォーマットのどれでも使用することができます。

レスポンス・コードは多くの場合、HTTP のステータス・コードです。この仕組みのメリットは、既存のよく知られたステータス・コードを使って、エラーなのか成功したのかを特定できることです。ステータス・コード 201 (CREATED) は、POST リクエストが成功した場合の理想的なレスポンスです。エラー・コード 500 はサーバー側の問題でリクエストが失敗したことを示しますが、エラー・コード 400 はクライアント側の問題で失敗したことを示します (BAD REQUEST)。サーバーに何らかの問題がある場合には 503 (SERVICE UNAVAILABLE) を送信します。

以下の例を考えてみてください。あるアプリケーションが、ユーザー情報 (苗字、名前、E メール・アドレス、Twitter アカウント) を含むデータ・ソースを持っているとします。典型的な PHP アプリケーションを作成しているのであれば、mysql_query() ラッパーを作成し、SQL クエリーを使用してデータベースからリストを抽出します。また、その関数を呼び出す簡単な PHP コードによって、結果セットをループ処理し、アプリケーションのビューにデータを表示します。

もっと簡単な方法は、単純な REST コントローラーを作成する方法です。その REST コントローラーによって /users/list に対して他にパラメーターを指定せずに GET リクエストを発行すると、適切なデータベース関数が呼び出され、リストが JSON フォーマットで返されます。次に、アプリケーションはその JSON データをデコードし、必要に応じてデータをループ処理して内容を表示します。

また、/users/list に何らかのパラメーターが送信されたかどうかをテストすることもできます。例えば /users/list/1 に GET リクエストを送信すると、そのレスポンスには ID が 1 のユーザーの詳細のみが含まれます。さらに、JSON 以外のフォーマット (XML、CSV、シリアライズされた PHP など) を使用することもできます。

RESTful な JSON コントローラーの機能は、ビューとデータ・ソースとの間に機能レイヤーを追加して開発を支援することだけではありません。例えば、情報を要求するのは基本的な PHP ビューのみではない、という場合を考えてみてください。例えば、Ajax インターフェースを介して jQuery を使って情報を要求する場合や、ユーザーがスマートフォンや Facebook アプリケーションを介して情報を要求する場合があるかもしれません。

そうした場合、リクエストを受け付け、理解しやすい (そして予測しやすい) フォーマットでレスポンスを提供する RESTful なインターフェースによって、開発作業を大幅に単純化することができます。皆さんは PHP のビューを担当する開発者として (さらには iPhone アプリケーションの開発者として)、URL にリクエストを送信するだけで、期待通りの一連のレスポンスを受信することができます。この JSON コントローラーの反対側では、アプリケーションを MySQL や PostgreSQL、XML ファイル・リポジトリーなどに接続することも、まったく何にも接続しないままにすることもできます。


JSON とは何か

JSON はテキスト・ベースの軽量なデータ交換フォーマットであり、このフォーマットは人間にもコンピューターにも容易に理解すること、また容易に使用することができます。JSON は当初、単純なデータ構造を表現するために設計されました。元々は JavaScript で扱いやすいデータを伝送するための専用手段と考えられていましたが、現在はほとんどすべてのコンピューター言語に JSON 用のパーサーが用意されています。PHP に関して言えば、面倒な作業の大部分を処理してくれるネイティブの JSON 関数のペアがあります (json_encodejson_decode)。単純にデータの配列を (さらには単純なストリングを) json_encode に渡すと、JSON オブジェクトが作成されます (リスト 1)。

リスト 1. PHP の配列と JSON オブジェクト
$data = array(
	'firstname' => 'Tom', 
	'lastname' => 'Smith', 
	'age' => 40
);

print_r($data);
/* prints 
Array( 
	[firstname] => Tom
	[lastname] => Smith
	[age] => 40
)
*/

echo json_encode($data);

/* prints
	{ "firstname": "Tom",
	  "lastname": "Smith",
	  "age":40
	}	
*/

SQL クエリーによって得られる典型的な PHP 配列 (キーはデータベースのフィールド名に一致し、値はデータに一致します) は、JSON オブジェクトとして容易に伝送できることに注目してください。このデータが到着すると、そのデータは単純に (例えば、Ajax コンテキストの中から) JavaScript コードの eval() によって評価されるか、あるいは PHP の json_decode() によってデコードされ、再びデータの配列に戻ります。

JSON データは、オブジェクト以外にもさまざまなデータ型をサポートしています (ストリング、ヌル値、数値 (整数または実数)、ブール値、配列 (角括弧に囲まれ、カンマで区切られた連続的な値) など)。そのため、JSON を使うことでデータの扱いが非常に柔軟になります。

この記事では、モデル機能とビュー機能との間に配置できる最小限の JSON REST コントローラーを作成する方法について説明します。いったんこのコントローラーを作成すると、プロジェクトの目的に合わせて独自の拡張を行うことができます。

基本的な JSON コントローラーを作成する

イベント情報を提供するアプリケーションを考えてみてください。すべてのイベント情報は公開されています。そのため、ここでは認証の問題は大きな懸念事項ではありません。またこのアプリケーションの目的は、今日発生しているイベントに関して問い合わせできるようにし、JSON を使ってリクエストの発行者にレスポンスを返送することです。ここでははまず、リクエスターが PHP のビュー・ページであるとします。

まず、イベントに対する単純なデータベース・スキーマとして、リスト 2 のようなスキーマを作成します。

リスト 2. データベース・スキーマ (MySQL)
CREATE TABLE  `events` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 255 ) NOT NULL ,
`address` VARCHAR( 255 ) NOT NULL ,
`start_time` DATETIME NOT NULL ,
`description` TEXT NOT NULL
);

データベース・テーブルが動作するようになったら、いくつかのモック・データ・レコードを入力します。少なくとも一日に複数のエントリーが予定されているようにします。

次に、このデータベースに接続して SQL クエリーを使ってイベントを識別する、典型的な PHP のモデル・ファイルを作成します。実際のアプリケーションであれば、データベースに接続するためのスクリプトを他の部分から分離し、ありとあらゆるデータ検証をクエリーの中で行うはずです。このコードはリスト 3 のようなものです。

リスト 3. 単純なクエリー
$SERVER = 'name';
$USER = 'username';
$PASS = 'pw';
$DATABASE = 'dbname';


if (!($mylink = mysql_connect( $SERVER, $USER, $PASS)))
{
	echo "Sorry, could not connect to DB. Contact your sysadmin for help!";
	exit;
}
mysql_select_db( $DATABASE );


class Events{

	function get_events($day){
		$ret_array = array();
		$sql = "select id,title,address,start_time,description 
				from events where start_time like '$day%'
				order by start_time asc";
		$result = mysql_query($sql);

		while($data = mysql_fetch_object($result)){
			$obj['id'] = $data->id;
			$obj['title'] = $data->title;
			$obj['address'] = $data->address;
			$obj['start_time'] = $data->start_time;
			$obj['description'] = $data->description;

			$ret_array[] = $obj;
		}	

		return $ret_array;
	}
}

何らかのイベントが取得されることがわかっている日付を指定して、この関数を単純に呼び出すように設定すると、リスト 4 のような結果が得られます。

リスト 4. クエリーを実行した結果
$EVENT = new Events;
$today = '2010-06-17';
$events = $EVENT->get_events($today);

print_r($events);

/* results in
	Array
	(
		[0] => Array
			(
				[id] => 2
				[title] => Event #2
				[address] => 156 My Avenue, MyTown, USA 78727
				[start_time] => 2010-06-17 11:30:00
				[description] => Join us for lunch to hear 
					FABULOUS SPEAKER. 
			)

		[1] => Array
			(
				[id] => 1
				[title] => Event #1
				[address] => 123 My Street, Anytown USA 78727
				[start_time] => 2010-06-17 15:30:00
				[description] => A great event! Hope to see you there!
			)

	)
*/

同じコードを json_encode() を使って実行すると、移植可能な JSON オブジェクトが得られます (リスト 5)。

リスト 5. JSON データ・オブジェクト
[
{"id":"2",
"title":"Event #2",
"address":"156 My Avenue, MyTown, USA 78727",
"start_time":"2010-06-17 11:30:00",
"description":"Join us for lunch to hear FABULOUS SPEAKER. "
},
{"id":"1",
"title":"Event #1",
"address":"123 My Street, Anytown USA 78727",
"start_time":"2010-06-17 15:30:00",
"description":"A great event! Hope to see you there!"
}
]

目標は、どのモデルと関数を実行すればよいかを理解している単純なコントローラーを作成することです。そしてこのコントローラーは、トランザクション処理が行われているのと反対側で使用可能なレスポンスとして、JSON オブジェクトを返します。このコントローラーはリスト 6 のように非常に簡潔です。このコード全体を、json.php というファイルに貼り付けます。

リスト 6. 単純なコントローラー
class JSON{

	var $response = '';

	function JSON($model,$function,$params){
		$REQUEST = new $model;
		$data = $REQUEST->$function($params);
		$this->response = json_encode($data);
	}
}

このコードを動作させるためには、呼び出し対象のモデルを要求し、JSON クラスをインスタンス化し、それから 3 つのパラメーター (モデルのクラス名、実行対象の関数、その関数の引数) を渡します。すると、このクラスはその関数を呼び出して、json_encode() を実行した結果をレスポンスとして受け取ります。

最後のステップとして、JSON データに対するリクエストを含むファイルを作成します。この特定の (listing.php という名前の) ファイルを設定して 3 つの GET 変数 (それぞれ、モデル用、関数用、引数用) を受け付けるようにし、これらの変数を JSON クラスに渡します (リスト 7)。

リスト 7. リクエストのためのコード
//this is the code that contains the model
require 'events.php'; 

//this is the JSON controller
require 'json.php';

//pass in your three GET parameters
$MODEL = $_GET['model'];
$FUNCTION = $_GET['function'];

//check to see if param is passed in
//if not, use today's date in this instance
if (isset($_GET['param'])){
	$PARAM = $_GET['param'];
}else{
	$PARAM = date("Y-m-d");
}				
//invoke 
$JSON = new JSON($MODEL,$FUNCTION,$PARAM);

//access the response variable
echo $JSON->response;

この時点で、このファイルをブラウザーにロードすると、リスト 5 のような JSON オブジェクトを取得することができます。この JSON オブジェクトを json_decode() を使って返送し、JavaScript コードによって処理することもでき、あるいはそのままにすることもできます。

このプロセス全体に関するもっと適切な方法として、RESTful なサーバーをもっと厳密にエミュレートするパス構造を作成する方法があります。例えば、events/today というディレクトリー構造を作成し、そこに index.phpというファイルを格納します。ブラウザーで /events/today にアクセスすると、リスト 8 のコードによって JSON のフィードを取得することができ、GET に関する変数を渡す必要がありません。

リスト 8. /events/today/index.php のコード
require '../../events.php';
require '../../json.php';


$MODEL = "Events";
$FUNCTION = "get_events";
$PARAM = date("Y-m-d");


//invoke 
$JSON = new JSON($MODEL,$FUNCTION,$PARAM);	
echo $JSON->response;

//prints out
[
{"id":"3",
"title":"Test Event 3",
"address":"111 Main Street, Austin TX 78727",
"start_time":"2010-06-10 15:15:00",
"description":"Testing 456."
}
]

まとめ

この記事で説明した方法を使うことで、ビューやサポートしているアプリケーションでのデータ抽出に関する要件の一部を単純化することができます。ベースとなるデータベースの詳細をすべて記憶しなくても、単純に URL にアクセスするだけで、作業を進めるために必要なレスポンスを取得することができます。

参考文献

学ぶために

  • JSON について学んでください。
  • PHP のサイトで JSON に関するドキュメントを読んでください。
  • developerWorks の Web development ゾーンは Web ベースのさまざまなソリューションを解説した記事に特化しています。
  • developerWorks の Technical events and webcasts で最新情報を入手してください。
  • developerWorks On demand demos をご覧ください。初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。

製品や技術を入手するために

  • IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2®、Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=521218
ArticleTitle=Web プロジェクトのための単純な JSON コントローラーを作成する
publish-date=08102010