
PHP Web アプリケーションでの Ajax 入門
このドキュメントでは、Ajax の概要を説明し、Ajax 関連のテクノロジを使用するときにより短時間で効率よくプログラミングできる NetBeans IDE の機能を示します。Ajax の基本的な機能を学びながら、テキストフィールドの自動補完を行う簡単なアプリケーションを作成します。このドキュメントでは、「Java テクノロジを使用する Ajax の使用」に公開している Greg Murray の記事とサンプルアプリケーションを使用します。
Ajax は「Asynchronous JavaScript and XML」(非同期 JavaScript と XML) の略です。Ajax は基本的に、ユーザーによる Web ページの操作を Web アプリケーションで効率的に処理する方法であり、ユーザーが操作するたびにページを再表示したり、ページ全体を再読み込みしたりする必要を減らします。その結果、デスクトップアプリケーションやプラグインに基づいた Web アプリケーションのような、ブラウザを使用したスムーズな操作が可能になります。Ajax の相互作用はバックグラウンドで非同期で処理されます。このとき、ユーザーはページの操作を続けることができます。Ajax の相互作用は JavaScript コードによって開始されます。Ajax の相互作用が完了したら、JavaScript がそのページの HTML ソースを更新します。変更は、ページを再表示することなく、すぐに反映されます。Ajax の相互作用を使用して、ユーザーがフォームに入力している間にサーバー側ロジックを使用してその内容を検査したり、サーバーから詳細なデータを取り出したり、ページ上のデータを動的に更新したり、ページから部分フォームを送信したりできます。
目次

このチュートリアルを完了するには、次のソフトウェアとリソースが必要です。
注
- 使用しているオペレーティングシステムによっては、*AMP パッケージを使用して PHP の開発環境を構成できる場合があります。このパッケージには PHP エンジンと Apache Web サーバーが含まれます。環境の構成方法については、「PHP の学習」を参照してください。
- このチュートリアルは、使用する各テクノロジ (HTML、CSS、JavaScript、および PHP など) に関する実用的な知識がある方を対象としています。コードが提供する機能の概要は説明しますが、コード行ごとの処理は説明しません。
- プロジェクトを、正常に機能するソリューションと比較する必要がある場合は、サンプルアプリケーションをダウンロードできます。IDE の「新規プロジェクト」ウィザード (Ctrl-Shift-N、Mac の場合は ⌘-Shift-N) で「PHP」を選択し、「既存のソースを使用する PHP アプリケーション」プロジェクトタイプを選択します。ウィザードで、コンピュータにダウンロードされているソースを指定します。
アプリケーションの概要
ユーザーが作曲家に関する情報を検索できる Web ページを考えます。このページには、ユーザーが作曲家の名前を入力できるフィールドがあります。サンプルアプリケーションの入力フィールドには、自動補完機能があります。つまり、ユーザーが作曲家の名前の一部を入力すると、入力した文字から氏名のいずれかが始まる作曲家のリストが表示されます。自動補完機能によってユーザーは作曲家の名前を完全に覚えている必要がなく、また求めている情報を直感的に、かつすんなりと入手できます。
検索フィールドへの自動補完の実装は、Ajax を使用して実行できます。Ajax は、XMLHttpRequest オブジェクトを使用してクライアントとサーバーの間で要求と応答を非同期で受け渡しすることで機能します。次の図は、クライアントとサーバーの間で行われる通信のプロセスフローを示します。
この図には、次の手順のプロセスフローを示しています。
- ユーザーが、たとえば名前を入力しているときにキーを解除して、イベントをトリガーします。すると、
XMLHttpRequest オブジェクトを初期化する関数への JavaScript 呼び出しが行われます。
XMLHttpRequest オブジェクトが、イベントをトリガーしたコンポーネントの ID を含む要求パラメータと、ユーザーが入力した値で構成されます。次に XMLHttpRequest オブジェクトが Web サーバーへの非同期要求を実行します。
- Web サーバーでは、サーブレットやリスナーなどのオブジェクトが要求を処理します。データストアからデータが取り出され、XML 形式のデータを含む応答が作成されます。
- 最後に、コールバック関数を使用して
XMLHttpRequest オブジェクトが XML データを受け取って処理し、新しいデータを含むページを表示するように HTML の DOM (文書オブジェクトモデル) を更新します。
このチュートリアルでは、前出の図で示したプロセスフローに従って自動補完のシナリオを構築する方法を示します。最初に、プレゼンテーション用、および XMLHttpRequest オブジェクトの生成に必要な機能用のクライアント側ファイルを作成します。次に、PHP テクノロジを使用してデータストアとビジネスロジックを作成してサーバー側を設定します。最後に、クライアント側に戻り、callback() と、HTML の DOM を更新するためのその他の JavaScript 機能を実装します。
クライアント側のプログラミング: 第 1 部
最初に IDE で新しい PHP アプリケーションプロジェクトを作成します。
- 「ファイル」>「新規プロジェクト」を選択します。「カテゴリ」で「PHP」を選択します。「プロジェクト」で「PHP アプリケーション」を選択し、「次へ」をクリックします。
- ステップ 2 の「名前と場所」で、プロジェクト名に「
MyAjaxApp」と入力します。「ソースフォルダ」フィールドでコンピュータ上でのプロジェクトの場所を指定できます。ほかのオプションはデフォルトのままにして、「次へ」をクリックします。

- ステップ 3 の「実行構成」で、アプリケーションの配備方法を指定します。*AMP パッケージを構成して PHP 開発環境を設定した場合は、ドロップダウンリストから「ローカル Web サイト」を選択し、ブラウザに表示するプロジェクトの URL を指定します。
- 「ファイルをソースフォルダから別の場所にコピー」オプションを選択します。次に、「フォルダにコピー」フィールドに、サーバー上の配備先のパスを入力します。Apache では、デフォルトの
htdocs ディレクトリを使用します。

- 「完了」をクリックします。IDE によってプロジェクトフォルダがファイルシステム内に作成され、プロジェクトが IDE で開きます。
プロジェクトウィザードを使用して、 Symphony フレームワークのサポートをプロジェクトに追加することもできます (ウィザードのステップ 4)。
デフォルトの index.php インデックスページが生成され、IDE のエディタで開きます。また、「プロジェクト」ウィンドウにプロジェクトが表示されます。

- コーディングを始める前に、アプリケーションを実行してみて、IDE、サーバー、ブラウザの間の構成が正しく設定されていることを確認します。
IDE のエディタで、index ページに次の echo 文を追加します。
<?php
// put your code here
echo "<h2>Hello World!</h2>";
?>
- 「プロジェクト」ウィンドウでプロジェクトノードを右クリックし、「実行」を選択します。IDE によってデフォルトのブラウザが開き、
index.php で作成したメッセージ「Hello World」が表示されます。
注: プロジェクトを設定できない場合、または IDE、サーバー、およびブラウザ間で通信を確立できない場合は、「PHP プロジェクトの設定」を参照して、詳細な手順を確認してください。環境の構成については、「PHP の学習」を参照してください。
HTML エディタの使用
環境が正しく設定されていることを確認したら、まず、ユーザーに表示する自動補完インタフェースの開発から始めます。作成するインデックスページにはサーバー側のスクリプト要素は必要ないため、まず HTML ページを作成し、そのページをアプリケーションのエントリポイントとして設定します。
IDE を使用するメリットの 1 つは、作業を行うエディタには一般にコード補完機能が用意されていて、コーディングするときに適用すれば生産性を大幅に向上できることです。IDE のエディタは通常、使用しているテクノロジに適応するので、HTML ページの作業を行なっているときにコード補完のキーの組み合わせ (Ctrl- スペース) を押すと HTML のタグと属性の候補が表示されます。あとで示しますが、CSS や JavaScript などその他のテクノロジも同様です。
IDE のパレットも便利な機能です。パレットには、コーディングするテクノロジで一般的に適用する要素の、使いやすいテンプレートが用意されています。項目をクリックし、ソースエディタで開いているファイル内の任意の位置にドラッグするだけです。
この図のように大きなアイコンを表示するには、パレット内を右クリックし、「大きなアイコンを表示」を選択します。
- 「プロジェクト」ウィンドウで「
MyAjaxApp」プロジェクトノードを右クリックし、「新規」>「HTML ファイル」を選択します。
- 「新規 HTML ファイル」ウィザードで、ファイル名に「
index」と入力し、「完了」をクリックします。新しい index.html ファイルがエディタで開きます。
- このファイルの既存の内容を次の内容に置き換えます。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Auto-Completion using AJAX</title>
</head>
<body>
<h1>Auto-Completion using AJAX</h1>
</body>
</html>
- テキストフィールドの目的を説明するテキストを追加します。次のテキストをコピーし、
<h1> タグのすぐ下にペーストしてもかまいません。
<p>This example shows how you can do real time auto-completion using Asynchronous
JavaScript and XML (Ajax) interactions.</p>
<p>In the form below enter a name. Possible names that will be completed are displayed
below the form. For example, try typing in "Bach," "Mozart," or "Stravinsky,"
then click on one of the selections to see composer details.</p>
- ページに HTML フォームを追加します。この操作を行うには、IDE のパレットに表示されている要素を使用します。パレットが開いていない場合は、メインメニューから「ウィンドウ」>「パレット」を選択します。次に「HTML フォーム」の下にある「フォーム」要素をクリックし、ページ内に追加した
<p> タグの下までドラッグします。「挿入フォーム」ダイアログが表示されます。次の値を指定します。
- アクション: autocomplete.php
- メソッド: GET
- 名前: autofillform
「了解」をクリックします。指定した属性を含む HTML の <form> タグがページに挿入されます。GET はデフォルトで適用されるので、明示的に宣言しません。
- HTML 表をページに追加します。パレットの「HTML」カテゴリの下で「表」要素をクリックし、
<form> タグの間の任意の位置までドラッグします。「挿入 表」ダイアログが開きます。次の値を指定します。
- 行: 2
- 列: 2
- ボーダーのサイズ: 0
- セルのパディング: 5
- ソースエディタ内を右クリックし、「整形」を選択します。これでコードの体裁が整います。フォームは次のようになります。
<form name="autofillform" action="autocomplete.php">
<table border="0" cellpadding="5">
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</form>
- 表の 1 行目の 1 列目に次のテキストを入力します (ボールド部分が変更箇所)。
<td><strong>Composer Name:</strong></td>
- 1 行目の 2 列目では、パレットから「テキスト入力」フィールドをドラッグしないで、次のコードを手作業で入力します。
<input type="text"
size="40"
id="complete-field"
onkeyup="doCompletion();">
入力するときは、IDE に組み込まれているコード補完機能を使用してみてください。たとえば、「<i」と入力して Ctrl- スペースキーを押します。カーソルの下に候補のリストが表示され、選択されている要素の説明が上のボックスに表示されます。ソースエディタでコーディングしているときはいつでも Ctrl- スペースキーを押して候補リストを表示できます。候補が 1 つだけの場合は、Ctrl- スペースキーを押すと要素名が自動的に補完されます。
入力した onkeyup 属性は JavaScript 関数 doCompletion() を指しています。この関数は、フォームのテキストフィールド内でキーが押されるたびに呼び出され、Ajax のフロー図に示した JavaScript 呼び出しに対応します。
- JavaScript エディタでの作業に移る前に、アプリケーションのエントリポイントの
index.php ファイルを新しい index.html ファイルに置き換えます。
これを行うには、「プロジェクト」ウィンドウでプロジェクトノードを右クリックし、「プロパティー」を選択します。「実行構成」カテゴリを選択し、「開始ファイル」フィールドに「index.html」と入力します。
- 「了解」をクリックして変更を保存し、「プロジェクトプロパティー」ウィンドウを終了します。
- プロジェクトを実行して、ブラウザでどのように表示されるかを確認します。「プロジェクトを実行」(
) ボタンをクリックします。index.html ファイルがデフォルトのブラウザに表示されます。
JavaScript エディタの使用
IDE の JavaScript エディタには多数の高度な編集機能が用意されています。たとえば、インテリジェントなコード補完、意味解釈の強調表示、名前の即時変更機能とリファクタリング機能などがあります。概要については「JavaScript の編集」を、詳細な仕様については、http://wiki.netbeans.org/JavaScript を参照してください。
JavaScript のコード補完は、.js ファイル内でコーディングするとき、またほかのテクノロジ (HTML、RHTML、JSP、PHP など) を使用しているときに <script> タグ内で自動的に提供されます。JavaScript エディタには、JavaScript の「オプション」パネルで指定するブラウザの種類とバージョンに従って、ブラウザの互換性情報が表示されます。JavaScript の「オプション」パネルを開くには、「ツール」>「オプション」(Mac の場合は「NetBeans」>「設定」) を選択してから「その他」>「JavaScript」を選択します。
IDE では、Firefox、Internet Explorer、Safari、および Opera をデフォルトでサポートしています。JavaScript の「オプション」パネルでは、コード補完を適用する JavaScript エンジンのバージョンを指定することもできます。
アプリケーションに JavaScript ファイルを追加し、doCompletion() の実装を始めます。
- 「プロジェクト」ウィンドウでプロジェクトノードを右クリックし、「新規」>「JavaScript ファイル」を選択します。「JavaScript ファイル」がリストにない場合は「その他」を選択します。次に、「新規ファイル」ウィザードで「その他」カテゴリから「JavaScript ファイル」を選択します。
- ファイル名を
javascript にし、「完了」をクリックします。新しい JavaScript ファイルが「プロジェクト」ウィンドウに表示され、エディタで開きます。
- 次のコードを
javascript.js に入力します。
var req;
var isIE;
function init() {
completeField = document.getElementById("complete-field");
}
function doCompletion() {
var url = "autocomplete.php?action=complete&id=" + escape(completeField.value);
req = initRequest();
req.open("GET", url, true);
req.onreadystatechange = callback;
req.send(null);
}
function initRequest() {
if (window.XMLHttpRequest) {
if (navigator.userAgent.indexOf('MSIE') != -1) {
isIE = true;
}
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
isIE = true;
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
上のコードは、Firefox 3 および Internet Explorer version 6 と 7 の簡単なブラウザ互換性チェックを行います。互換性の問題に対してさらに堅牢なコードを取り込むには、http://www.quirksmode.org のブラウザ検出スクリプトを使用することを検討してください。
index.html に戻り、JavaScript ファイルへの参照を <head> タグの間に追加します。
<script type="text/javascript" src="javascript.js"></script>
Ctrl-Tab キーを押すと、エディタ内で開いているページを簡単に切り替えることができます。
init() への呼び出しを開始 <body> タグ内に挿入します。
<body onload="init()">
このようにすると、ページが読み込まれるたびに init() が呼び出されます。
doCompletion() には次の役割があります。
- サーバー側で利用できるデータを含む URL を作成すること
XMLHttpRequest オブジェクトを初期化すること
- 非同期要求をサーバーに送信するように
XMLHttpRequest オブジェクトに要求すること
XMLHttpRequest オブジェクトは Ajax の中核であり、HTTP を使用して XML データを非同期で送信するときの事実上の標準になっています。相互作用が非同期であるということは、要求の送信後にブラウザで引き続きイベントを処理できることを意味します。データはバックグラウンドで送信され、ページを再表示しないで自動的にページに読み込むことができます。
XMLHttpRequest オブジェクトは実際には initRequest() で作成し、これは doCompletion() から呼び出されます。この関数では、ブラウザで XMLHttpRequest を理解できるかどうかを確認し、理解できる場合は XMLHttpRequest オブジェクトを作成します。理解できない場合は、ActiveXObject (Internet Explorer 6 で XMLHttpRequest に相当するもの) を確認し、識別された場合は ActiveXObject を作成します。
XMLHttpRequest オブジェクトを作成するときは 3 つのパラメータを指定します。URL、HTTP メソッド (GET または POST)、そして相互作用が非同期であるかどうかです。前出の例では、これらのパラメータは次のとおりです。
- URL
autocomplete.php と、ユーザーが complete-field に入力したテキスト
var url = "autocomplete.php?action=complete&id=" + escape(completeField.value);
GET (HTTP の相互作用で GET メソッドを使用)
true (相互作用は非同期)
req.open("GET", url, true);
相互作用を非同期に設定する場合は、コールバック関数を指定します。この相互作用のコールバック関数は次の文で設定します。
req.onreadystatechange = callback;
そして callback() 関数をあとで定義する必要があります。HTTP の相互作用は XMLHttpRequest.send() の呼び出し時に開始します。このアクションは、前出のフロー図で Web サーバーに送信されている HTTP 要求に対応します。
サーバー側のプログラミング
NetBeans IDE では、PHP を使用した Web 開発が総合的にサポートされています。*AMP パッケージを使用して開発環境を設定し、IDE で短時間で効率よく編集と配備ができます。IDE では、ローカルサーバーだけでなく、FTP または SFTP を使用してリモートでも環境を設定できます。また、Xdebug など外部のデバッガを設定し、IDE の「オプション」ウィンドウ (「ツール」>「オプション」を選択、Mac の場合は「NetBeans」>「設定」を選択) の「PHP」タブで、PHPUnit を使用した単体テストを設定できます。PHP エディタには、コード補完、構文の強調表示、出現箇所のマーク、リファクタリング、コードテンプレート、ドキュメントのポップアップ、コードナビゲーション、エディタの警告、および NetBeans 6.9 の場合は形式の不正な構文のエラーバッジなどの、標準の編集機能があります。PHP サポートのスクリーンキャストについては、「NetBeans のビデオチュートリアルとデモ」ページを参照してください。
アプリケーションにデータベースが必要な場合、IDE では、ほとんどの主なデータベース、特に MySQL がサポートされています。詳細は、NetBeans の MySQL のスクリーンキャストとデータベース統合の説明を参照してください。
ここで作成している自動補完アプリケーションのビジネスロジックでは、データストアからデータを取り出して要求を処理し、応答を作成して送信する必要があります。これは、autocomplete という名前の PHP ファイルを使用して、ここで実装します。ファイルのコーディングを始める前に、データストアと、ファイルからデータにアクセスするために必要な機能を設定します。
データストアの作成
この簡単なアプリケーションでは、ビジネスロジックで composers 配列に含まれるエントリからデータを取得できるようにする Composer というクラスを作成します。次に、その配列を使用して作曲家のデータを保持する ComposerData というクラスを作成します。
- 「プロジェクト」ウィンドウで「
MyAjaxApp」プロジェクトノードを右クリックし、「新規」>「PHP クラス」を選択します。
- クラス名を
Composer にし、「完了」をクリックします。クラスが作成され、エディタで開きます。
- 次のコードをクラス内にペーストします (変更箇所はボールドで表示)。
<?php
class Composer {
public $id;
public $firstName;
public $lastName;
public $category;
function __construct($id, $firstName, $lastName, $category) {
$this->id = $id;
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->category = $category;
}
}
?>
ComposerData クラスを作成します。
- 「プロジェクト」ウィンドウで
MyAjaxApp プロジェクトノードを右クリックし、「新規」>「PHP クラス」を選択します。
- クラス名を
ComposerData にし、「完了」をクリックします。クラスが作成され、IDE のエディタで開きます。
require 文をクラスの先頭に追加し、作成した Composer.php クラスをこのクラスが要求するように指定します (変更箇所は ボールドで表示)。
<?php
require "Composer.php";
class ComposerData {
}
- エディタで、次のコードをクラス内にペーストします (変更箇所はボールドで表示)。
<?php
require "Composer.php";
class ComposerData {
public $composers;
function __construct() {
$this->composers = array(
new Composer("1", "Johann Sebastian", "Bach", "Baroque"),
new Composer("2", "Arcangelo", "Corelli", "Baroque"),
new Composer("3", "George Frideric", "Handel", "Baroque"),
new Composer("4", "Henry", "Purcell", "Baroque"),
new Composer("5", "Jean-Philippe", "Rameau", "Baroque"),
new Composer("6", "Domenico", "Scarlatti", "Baroque"),
new Composer("7", "Antonio", "Vivaldi", "Baroque"),
new Composer("8", "Ludwig van", "Beethoven", "Classical"),
new Composer("9", "Johannes", "Brahms", "Classical"),
new Composer("10", "Francesco", "Cavalli", "Classical"),
new Composer("11", "Fryderyk Franciszek", "Chopin", "Classical"),
new Composer("12", "Antonin", "Dvorak", "Classical"),
new Composer("13", "Franz Joseph", "Haydn", "Classical"),
new Composer("14", "Gustav", "Mahler", "Classical"),
new Composer("15", "Wolfgang Amadeus", "Mozart", "Classical"),
new Composer("16", "Johann", "Pachelbel", "Classical"),
new Composer("17", "Gioachino", "Rossini", "Classical"),
new Composer("18", "Dmitry", "Shostakovich", "Classical"),
new Composer("19", "Richard", "Wagner", "Classical"),
new Composer("20", "Louis-Hector", "Berlioz", "Romantic"),
new Composer("21", "Georges", "Bizet", "Romantic"),
new Composer("22", "Cesar", "Cui", "Romantic"),
new Composer("23", "Claude", "Debussy", "Romantic"),
new Composer("24", "Edward", "Elgar", "Romantic"),
new Composer("25", "Gabriel", "Faure", "Romantic"),
new Composer("26", "Cesar", "Franck", "Romantic"),
new Composer("27", "Edvard", "Grieg", "Romantic"),
new Composer("28", "Nikolay", "Rimsky-Korsakov", "Romantic"),
new Composer("29", "Franz Joseph", "Liszt", "Romantic"),
new Composer("30", "Felix", "Mendelssohn", "Romantic"),
new Composer("31", "Giacomo", "Puccini", "Romantic"),
new Composer("32", "Sergei", "Rachmaninoff", "Romantic"),
new Composer("33", "Camille", "Saint-Saens", "Romantic"),
new Composer("34", "Franz", "Schubert", "Romantic"),
new Composer("35", "Robert", "Schumann", "Romantic"),
new Composer("36", "Jean", "Sibelius", "Romantic"),
new Composer("37", "Bedrich", "Smetana", "Romantic"),
new Composer("38", "Richard", "Strauss", "Romantic"),
new Composer("39", "Pyotr Il'yich", "Tchaikovsky", "Romantic"),
new Composer("40", "Guiseppe", "Verdi", "Romantic"),
new Composer("41", "Bela", "Bartok", "Post-Romantic"),
new Composer("42", "Leonard", "Bernstein", "Post-Romantic"),
new Composer("43", "Benjamin", "Britten", "Post-Romantic"),
new Composer("44", "John", "Cage", "Post-Romantic"),
new Composer("45", "Aaron", "Copland", "Post-Romantic"),
new Composer("46", "George", "Gershwin", "Post-Romantic"),
new Composer("47", "Sergey", "Prokofiev", "Post-Romantic"),
new Composer("48", "Maurice", "Ravel", "Post-Romantic"),
new Composer("49", "Igor", "Stravinsky", "Post-Romantic"),
new Composer("50", "Carl", "Orff", "Post-Romantic"),
);
}
}
?>
ビジネスロジックの作成
受信要求によって受け取る autocomplete URL を処理するロジックを実装します。前の節での説明のように「新規ファイル」ウィザードを使用して新しい PHP ファイルを作成する代わりに、ここでは既存の index.php ファイルを変更します。
- 「プロジェクト」ウィンドウで
index.php ファイルノードをクリックします。ファイル名が編集可能になり、名前を変更できるようになります。

- ファイル名を
autocomplete にし、Enter キーを押します。新しい autocomplete.php ファイルをダブルクリックし、エディタに表示します。
- このファイルの既存のコードを次のスクリプトに置き換えます。
<?php
require_once("ComposerData.php");
session_start();
$composerData = new ComposerData();
$composers = $composerData->composers;
$results = array();
$namesAdded = false;
// simple matching for start of first or last name, or both
if(isset($_GET['action']) && $_GET['action'] == "complete") {
foreach($composers as $composer) {
if(!is_numeric($_GET['id']) &&
// if id matches first name
(stripos($composer->firstName, $_GET['id']) === 0 ||
// if id matches last name
stripos($composer->lastName, $_GET['id']) === 0) ||
// if id matches full name
stripos($composer->firstName." ".$composer->lastName, $_GET['id']) === 0) {
$results[] = $composer;
}
}
// prepare xml data
if(sizeof($results) != 0) {
header('Content-type: text/xml');
echo "<composers>";
foreach($results as $result) {
echo "<composer>";
echo "<id>" . $result->id . "</id>";
echo "<firstName>" . $result->firstName . "</firstName>";
echo "<lastName>" . $result->lastName . "</lastName>";
echo "</composer>";
}
echo "</composers>";
}
}
// if user chooses from pop-up box
if(isset($_GET['action']) && isset($_GET['id']) && $_GET['action'] == "lookup") {
foreach($composers as $composer) {
if($composer->id == $_GET['id']) {
session_register("id");
session_register ("firstName");
session_register ("lastName");
session_register ("category");
$HTTP_SESSION_VARS ["id"] = $composer->id;
$HTTP_SESSION_VARS ["firstName"] = $composer->firstName;
$HTTP_SESSION_VARS ["lastName"] = $composer->lastName;
$HTTP_SESSION_VARS ["category"] = $composer->category;
header("Location: composerView.php");
}
}
}
?>
見ればわかるように、Ajax 処理用のサーバー側コードを記述するために新たに覚えることはありません。XML ドキュメントを交換する場合は、応答の内容の種類を text/xml に設定します。Ajax ではプレーンテキストを交換することもできます。JavaScript のスニペットの交換は、クライアントのコールバック関数によって評価または実行できます。一部のブラウザでは結果がキャッシュに保存される場合があるので、Cache-Control HTTP ヘッダーを no-cache に設定する必要がある場合もあります。
この例では、autocomplete.php ファイルによって XML ドキュメントが生成されます。この XML ドキュメントには、氏名のいずれかがユーザーが入力した文字で始まる作曲家がすべて含まれています。このドキュメントは、前出のフロー図に示す XML データに対応します。XMLHttpRequest オブジェクトに返される XML ドキュメントの例を示します。
<composers>
<composer>
<id>12</id>
<firstName>Antonin</firstName>
<lastName>Dvorak</lastName>
</composer>
<composer>
<id>45</id>
<firstName>Aaron</firstName>
<lastName>Copland</lastName>
</composer>
<composer>
<id>7</id>
<firstName>Antonio</firstName>
<lastName>Vivaldi</lastName>
</composer>
<composer>
<id>2</id>
<firstName>Arcangelo</firstName>
<lastName>Corelli</lastName>
</composer>
</composers>
クライアント側のプログラミング: 第 2 部
サーバーの応答を処理するコールバック関数を定義し、ユーザーに表示するページに変更を反映するために必要な機能を追加する必要があります。そのためには HTML の DOM を変更する必要があります。最後に、IDE の CSS エディタを使用して、簡単なスタイルシートをプレゼンテーションに追加できます。
コールバック機能の追加
コールバック関数は、HTTP の相互作用中に XMLHttpRequest オブジェクトの「readyState」プロパティーが変化したとき、非同期で呼び出されます。ここで構築しているアプリケーションでのコールバック関数は callback() です。doCompletion() では、callback を関数の「XMLHttpRequest.onreadystatechange」プロパティーとして設定しました。ここで、コールバック関数を次のように実装します。
javascript.js をエディタで開き、次のコードを入力します。
function callback() {
if (req.readyState == 4) {
if (req.status == 200) {
parseMessages(req.responseXML);
}
}
}
readyState が「4」のとき、HTTP の相互作用は完了しています。XMLHttpRequest.readState の API は、設定できる値が 5 つあることを示します。これらを次に示します。
| 0 |
非初期化 |
| 1 |
読み込み中 |
| 2 |
読み込み済み |
| 3 |
対話式 |
| 4 |
完了 |
parseMessages() 関数は、XMLHttpRequest.readyState が「4」で、status (要求の HTTP 状態コード定義) が「200」、つまり成功の場合にのみ呼び出しています。parseMessages() は、次の「HTML DOM の更新」で定義します。
HTML DOM の更新
受信する XML データは parseMessages() 関数で処理します。このとき、appendComposer()、getElementY()、および clearTable() などの補助的関数を使用します。また、index ページに新しい要素を追加する必要があります。新しい要素には、自動補完ボックスとして機能する別の HTML 表や、要素を javascript.js で参照できるようするための要素の ID などがあります。最後に、index.php 内の要素の ID に対応する新しい変数を作成し、前に実装した init() 関数で初期化し、index.php が読み込まれるたびに必要とされる機能を追加します。
注: 次の手順で作成する関数と要素は、依存しあって動作します。この節の最後まで行い、コードが完成してからその内容を確認することをお勧めします。
index.html をエディタで開き、前に作成した HTML 表の 2 行目として次のコードを入力します。
<tr>
<td id="auto-row" colspan="2">
<td/>
</tr>
この新しい行は「auto-row」として識別できます。自動補完ボックスを形成する新しい HTML 表を挿入するための、JavaScript コード向けのハンドルの役割を果たします。
javascript.js をエディタで開き、次の 3 つの変数をファイルの先頭に追加します。
var completeField;
var completeTable;
var autoRow;
- 次のボールドの行を
init() 関数に追加します。
function init() {
completeField = document.getElementById("complete-field");
completeTable = document.createElement("table");
completeTable.setAttribute("class", "popupBox");
completeTable.setAttribute("style", "display: none");
autoRow = document.getElementById("auto-row");
autoRow.appendChild(completeTable);
completeTable.style.top = getElementY(autoRow) + "px";
}
init() の目的の 1 つは、インデックスページの DOM を変更するほかの関数から index.html 内の要素にアクセスできるようにすることです。上記のスクリプトは、新しい HTML 表を作成し、popupBox クラスを追加し、要素のスタイルを display: none に変更します。最後に、id が auto-row である要素を取得し、ここに新しい表を挿入します。つまり、このコードを実行するときには、変更された HTML は次のようになります。
<tr>
<td id="auto-row" colspan="2">
<table class="popupBox" style="display: none"></table>
<td/>
</tr>
appendComposer() を javascript.js に追加します。
function appendComposer(firstName,lastName,composerId) {
var row;
var cell;
var linkElement;
if (isIE) {
completeTable.style.display = 'block';
row = completeTable.insertRow(completeTable.rows.length);
cell = row.insertCell(0);
} else {
completeTable.style.display = 'table';
row = document.createElement("tr");
cell = document.createElement("td");
row.appendChild(cell);
completeTable.appendChild(row);
}
cell.className = "popupCell";
linkElement = document.createElement("a");
linkElement.className = "popupItem";
linkElement.setAttribute("href", "autocomplete.php?action=lookup&id=" + composerId);
linkElement.appendChild(document.createTextNode(firstName + " " + lastName));
cell.appendChild(linkElement);
}
この関数は、表に新しい行を作成し、3 つのパラメータによって関数に渡されたデータを使用して作曲家へのリンクを挿入してから、行を index ページの complete-table 要素に挿入します。
clearTable() を javascript.js に追加します。
function clearTable() {
if (completeTable.getElementsByTagName("tr").length > 0) {
completeTable.style.display = 'none';
for (loop = completeTable.childNodes.length -1; loop >= 0 ; loop--) {
completeTable.removeChild(completeTable.childNodes[loop]);
}
}
}
この関数は complete-table 要素の表示を 'none' に設定し (非表示にし)、作成された既存の作曲家の名前を削除します。
getElementY() を javascript.js に追加します。
function getElementY(element){
var targetTop = 0;
if (element.offsetParent) {
while (element.offsetParent) {
targetTop += element.offsetTop;
element = element.offsetParent;
}
} else if (element.y) {
targetTop += element.y;
}
return targetTop;
}
この関数は、親要素の縦方向表示位置を見つけるために適用します。要素の実際の表示位置は、一般にブラウザの種類とバージョンによって異なるためこの関数が必要です。complete-table 要素は、作曲家の名前が表示されるときに、表の右下に移動します。正しい縦方向の配置は getElementY() で決まります。
注: http://www.quirksmode.org/ にある offset に関する説明を参照してください。
callback() 関数を変更して、サーバーから新しいデータを受け取るたびに clearTable() を呼び出すようにします。自動補完ボックスに作曲家のエントリがある場合は、新しいエントリが入力される前に削除されます。
function callback() {
clearTable();
if (req.readyState == 4) {
if (req.status == 200) {
parseMessages(req.responseXML);
}
}
}
parseMessages() を javascript.js に追加します。
function parseMessages(responseXML) {
// 一致なし
if (responseXML == null) {
return false;
} else {
var composers = responseXML.getElementsByTagName("composers")[0];
if (composers.childNodes.length > 0) {
completeTable.setAttribute("bordercolor", "black");
completeTable.setAttribute("border", "1");
for (loop = 0; loop < composers.childNodes.length; loop++) {
var composer = composers.childNodes[loop];
var firstName = composer.getElementsByTagName("firstName")[0];
var lastName = composer.getElementsByTagName("lastName")[0];
var composerId = composer.getElementsByTagName("id")[0];
appendComposer(firstName.childNodes[0].nodeValue,
lastName.childNodes[0].nodeValue,
composerId.childNodes[0].nodeValue);
}
}
}
}
parseMessages() 関数は、autocomplete.php ファイルから返される XML ドキュメントのオブジェクト表現をパラメータとして受け取ります。この関数はプログラムで XML ドキュメント内を横断し、各エントリの firstName、lastName、および id を抽出して、このデータを appendComposer() に渡します。その結果、complete-table 要素の内容が動的に更新されます。たとえば、次のようなエントリが生成され、complete-table に挿入されます。
<tr>
<td class="popupCell">
<a class="popupItem" href="autocomplete?action=lookup&id=12">Antonin Dvorak</a>
</td>
</tr>
complete-table 要素の動的な更新は、Ajax を使用して行われる通信の、プロセスフローの最後の手順を表します。この更新は、前出のフロー図のプレゼンテーションに送信される HTML と CSS データに対応します。
スタイルシートの適用
これでアプリケーションの機能に必要なコードが完成しました。作業の結果を確認するため、今すぐアプリケーションを実行してみてください。
- プロジェクトを実行して、ブラウザでどのように表示されるかを確認します。「プロジェクトを実行」(
) ボタンをクリックします。index.html ファイルがブラウザに表示されます。

アプリケーションにスタイルシートを適用するには、階層式スタイルシート (CSS) ファイルを作成し、プレゼンテーションページからそのファイルにリンクします。CSS ファイルで作業する場合、IDE には、コード補完機能や、スタイルシート規則の作成に役立つほかのいくつかの機能が提供されています。これには次のものが含まれています。
- CSS スタイルビルダー: 一連のコントロールやウィジェットを使用して規則を作成できるインタフェースです。「ウィンドウ」>「その他」>「CSS スタイルビルダー」を選択します。
- CSS プレビュー: 規則内にカーソルを置くと、その規則の宣言ブロックに従ってサンプルテキストが描画されるプレビューウィンドウです。「ウィンドウ」>「その他」>「CSS プレビュー」を選択します。
- スタイル規則エディタ: クラス、ID、HTML 要素に基づいて規則を作成し、ドキュメント階層における位置を設定できるダイアログです。「規則を作成」(
) ボタンは、CSS エディタのツールバーの左上側にあります。
NetBeans 6.9 は、「名前の変更のリファクタリング」機能と「使用状況を検索」機能をサポートしています。これらの機能は、CSS ファイルだけでなく、CSS コードが埋め込まれているすべてのファイルでサポートされます (HTML、PHP など)。CSS のクラス、ID、およびタイプ要素を、すべてのプロジェクトファイルでリファクタリングできます。このリファクタリングのサポートを利用するには、任意の CSS 要素上で Ctrl-R キーを押し、表示されたダイアログで名前を変更します。また、名前を変更する前に変更をプレビューすることもできます。「使用状況を検索」機能のサポートを利用するには、CSS 要素を右クリックし、「使用状況を検索」を選択します。詳細については、「NewAndNoteworthy69m1」を参照してください。
スタイルシートをアプリケーションに適用するには、次の手順に従います。
- 「プロジェクト」ウィンドウでプロジェクトノードを右クリックし、「新規」>「階層式スタイルシート」を選択します (「階層式スタイルシート」が表示されない場合は、「その他」を選択します。次に、「新規ファイル」ウィザードで「その他」カテゴリから「階層式スタイルシート」を選択します)。
- 「CSS ファイル名」テキストフィールドに、「
stylesheet」と入力します。
- 「完了」をクリックします。CSS エディタ内を右クリックして「CSS の検査」を選択し、CSS コードの妥当性を検査します。
stylesheet.css に、次の規則を入力します。IDE のコード補完機能を利用するには、候補を呼び出したい場所で Ctrl- スペースキーを押します。
body {
font-family: sans-serif;
font-size: smaller;
padding: 50px;
color: #555;
width: 650px;
}
h1 {
letter-spacing: 6px;
font-size: 1.6em;
color: #be7429;
font-weight: bold;
}
h2 {
text-align: left;
letter-spacing: 6px;
font-size: 1.4em;
color: #be7429;
font-weight: normal;
width: 450px;
}
table {
width: 550px;
padding: 10px;
background-color: #c5e7e0;
}
td {
padding: 10px;
}
a {
color: #be7429;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.popupBox {
position: absolute;
top: 170px;
left: 140px;
}
.popupCell {
background-color: #fffafa;
}
.popupCell:hover {
background-color: #f5ebe9;
}
.popupItem {
color: #333;
text-decoration: none;
font-size: 1.2em;
}
CSS エディタ内を右クリックして「CSS の検査」を選択し、CSS コードの妥当性を検査します。エラーがあった場合は「出力」ウィンドウ (「ウィンドウ」>「出力」) に表示されます。
- 「ウィンドウ」>「その他」>「CSS プレビュー」を選択し、「CSS プレビュー」ウィンドウを開きます。
- テキストと色を変更する規則内にカーソルを置きます (たとえば
h1)。「CSS プレビュー」ウィンドウに、テキストがブラウザにどのように描画されるかを示すサンプル表示が生成されます。

- エディタで
index.html ページに切り替え (Ctrl-Tab キーを押します)、<head> タグの間にスタイルシートへの参照を追加します。
<link rel="stylesheet" type="text/css" href="stylesheet.css">
- アプリケーションをもう一度実行します。インデックスページが、作成したスタイルシートを使用してブラウザに表示されます。文字を入力するたびに非同期の要求がサーバーに送信され、
autocomplete.php によって作成された XML データが返されます。さらに文字を入力すると、新しい一致リストを反映して作曲家の名前の数が減ります。
まとめ
これで Ajax 入門を終了します。Ajax は単に HTTP を使用してバックグラウンドで情報を交換し、その結果に基づいてページを動的に更新していることをおわかりいただけましたでしょうか。
ここで作成したアプリケーションは完全ではありません。たとえば、自動補完ボックスで作曲家の名前を選択しても何も起こりません。サンプルアプリケーションをダウンロードし、PHP テクノロジを使用して、この処理を実装する方法を確認できます。また、ユーザーがデータストアにない名前を要求しないように検査する方法を検討することもできます。これらの手法については、NetBeans の「PHP の学習」にある、ほかのチュートリアルで紹介しています。
関連項目
netbeans.org での Ajax および PHP テクノロジについての詳細は、次のリソースを参照してください。
|
|