今回は,第3回に引き続きsearchAjax.html(リスト1)とsearchAjax.phpによるシンプルな検索アプリケーションの内容に踏み込んでいきます。前回はXMLHttpRequestオブジェクトを使用するための準備をするところまでを紹介しましたので,今回はいよいよXMLHttpRequestオブジェクトでサーバーに対して要求処理を行ってみることにします。

リスト1●AjaxアプリケーションのHTMLファイル(searchAjax.html)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>書籍検索</title>
<script language="JavaScript">
<!--
 // [送信]ボタンをクリック時の処理を定義
 function send() {
   // 非同期通信を行うためのXMLHttpRequestオブジェクトを生成
  try {
    xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
  } catch(e) {
    xmlReq = new XMLHttpRequest();
  }
   // サーバーからの応答時の処理を定義(結果のページへの反映)
  xmlReq.onreadystatechange = function() {
     var msg = document.getElementById("result");
     if (xmlReq.readyState == 4) {
      if (xmlReq.status == 200) {
        msg.innerHTML = xmlReq.responseText;
      } else {
        msg.innerHTML = "通信に失敗しました。";
      }
    } else {
      msg.innerHTML = "通信中…";
    }
  }
  
   // サーバーとの通信を開始
  xmlReq.open("GET","searchAjax.php?isbn="
                    + encodeURI(document.fm.isbn.value),true);
  xmlReq.send(null);
 }
//-->
</script>
</head>
<body>
<form name="fm">
ISBNコード:
<input type="text" name="isbn" size="30" />
<input type="button" value="送信" onclick="send()" />
<div id="result" />
</form>
</body>
</html>

サーバーに要求を送信する

 コールバック関数を定義できたら,あとはサーバーに対してリクエストを送信するだけです。リクエストを送信するには,まずopenメソッドでリクエストを開始する必要があります。

  xmlReq.open("GET","searchAjax.php?isbn="
                    + encodeURI(document.fm.isbn.value),true);

openメソッドの構文は,以下の通りです。

  XMLHttpRequest.open(HTTPメソッド ,URL [,非同期モードを使用するか
                      [,ユーザー名 [,パスワード]]])
  ※ 第3引数以降は任意

 比較的シンプルな情報を送信する場合には,HTTPメソッドは"GET"で構いません。GETメソッドでサーバーに対して情報を送信するには,URLの末尾に「?キー名=値」の形式で情報を追加します。値は,encodeURIメソッドであらかじめエンコード処理しておきましょう。本サンプルでは,テキストボックスから入力した値(isbn)を付与しているだけですが,複数の情報を付与したい場合には「&」区切りで複数の情報を列記することも可能です。

 第3引数には,HTTP通信を非同期で行うかどうかを指定します。連載のはじめにも述べたように,Ajaxは非同期通信を前提とした技術ですので,通常はtrueと指定しておけばよいでしょう。もしもここでfalseを指定した場合には,HTTP通信は同期モードで行われ,サーバーが処理を行っている間はクライアント側の処理を継続できません。

 リクエストの準備ができたら,あとはsendメソッドでリクエスト情報をサーバーに送信するだけです。openメソッドはあくまでリクエストの準備を行うだけですので,実際の情報はsendメソッドを呼び出すまで送信されません。

 sendメソッドの引数には,リクエスト時に送信する情報本体を指定します。

  xmlReq.send(null);

sendメソッドの引数は,openメソッドの第1引数として"POST"を指定した場合にのみ指定することが可能です。今回は"GET"メソッドを使用していますので,null(未定義)を指定しておきます。第3回にも説明しましたが,sendメソッドによる要求処理の結果は,onreadystateプロパティで指定したコールバック関数によって取得することができます。

注意
 セキュリティ上の理由から,XMLHttpRequestオブジェクトではopenメソッドのURL(第2引数)として異なるドメインを指定することはできません。使用しているブラウザの種類によっては,(同一ドメインに対する要求であっても)ドメイン名を指定するだけで正しく処理できないものもありますので,注意してください。openメソッドのURLには,サーバー内の相対パスを指定しておくのが無難でしょう。

POSTメソッドで情報を送信するには?

 GETメソッドはシンプルな情報を送信するには便利ですが,送信できる情報量に制限があるため(具体的なサイズは使用しているサーバーに依存します),数百バイト以上の情報を送信する場合にはPOSTメソッドを使用することをお勧めします。POSTメソッドでは,原則として送信できるデータ量に制限はありません。

 POSTメソッドを使用する場合には,searchAjax.htmlのリクエスト送信のコードを以下のように書き換える必要があります。

xmlReq.open("GET","searchAjax.php?isbn="
                  + encodeURI(document.fm.isbn.value),true);
xmlReq.send(null);
xmlReq.open("POST","searchAjax.php",true);
xmlReq.setRequestHeader("content-type",
  "application/x-www-form-urlencoded;charset=UTF-8");
xmlReq.send("isbn=" + encodeURI(document.fm.isbn.value));

 ポイントとなるのは2点です。

(1)Content-Typeヘッダーを設定する
 POSTメソッドで情報を送信する場合には,setRequestHeaderメソッドでContent-Typeヘッダーを指定する必要があります。Content-Typeヘッダーはリクエスト情報の種類を表すための情報です。Content-Typeヘッダーを指定しなかった場合,使用しているブラウザによってはサーバーに正しく情報を送信できませんので,注意してください(例えば,FireFoxなどではContent-Typeヘッダーに「text/xml」が自動セットされます)。「application/x-www-form-urlencoded;charset=UTF-8」は,通常,ブラウザからPOSTデータを送信する場合のデフォルトのContent-Typeです。

(2)データはsendメソッドで指定する
 GETメソッドでは送信すべき情報を「?キー名=値」の形式でURLの末尾に指定しましたが,POSTメソッドではsendメソッドの引数として指定します。GETメソッドの場合と同様,形式は「キー名=値&...」とし,値はencodeURI関数であらかじめエンコードしておく必要があります。

注意
 POSTメソッドで情報を送信した場合,サーバー側のコードにも若干の修正が必要になります。本サンプルの例であれば,「$_GET['isbn']」という部分を「$_POST['isbn']」に変更してください。

★ ★ ★

 以上,3回にわたって,Ajaxによるごく基本的なアプリケーションについて紹介してきました。これでクライアント/サーバー間でプレーン・テキストを受け渡しする方法について理解できたのではないかと思います。

 しかし,サーバー側から応答される情報はプレーン・テキストで表せるようなシンプルな情報ばかりとは限りません。構造化された複合的な情報を受け渡したいというケースのほうがはるかに多いはずです。次回は,Ajaxでそのような構造化データを受け渡しする方法について紹介します。

山田祥寛(やまだ よしひろ)

Microsoft MVP for ASP/ASP .NET。執筆コミュニティ「WINGSプロジェクト」の代表でもある。主な近著に「XMLデータベース入門」「PEAR入門」「Smarty入門」「10日でおぼえる入門教室シリーズ(Jakarta・JSP/サーブレット・PHP・XML)」(以上,翔泳社),「今日からつかえるサンプル集シリーズ(JSP&サーブレット・PHP5・ASP・XML)」(以上,秀和システム),「書き込み式 SQLのドリル」(ソシム),「JSP/PHP/ASPサーバーサイドプログラミング徹底比較」(技術評論社)など。最近では,IT関連技術の取材,講演,監修まで広く手がける毎日。